From a46f33b2144df0b913b50bb8c78256e20bce84c8 Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sat, 20 Aug 2022 16:37:51 -0400 Subject: [PATCH 001/148] Initial PDM driver --- embassy-nrf/src/chips/nrf52810.rs | 3 + embassy-nrf/src/chips/nrf52811.rs | 3 + embassy-nrf/src/chips/nrf52832.rs | 3 + embassy-nrf/src/chips/nrf52833.rs | 3 + embassy-nrf/src/chips/nrf52840.rs | 3 + embassy-nrf/src/lib.rs | 8 ++ embassy-nrf/src/pdm.rs | 185 ++++++++++++++++++++++++++++++ examples/nrf/Cargo.toml | 1 + examples/nrf/src/bin/pdm.rs | 34 ++++++ 9 files changed, 243 insertions(+) create mode 100644 embassy-nrf/src/pdm.rs create mode 100644 examples/nrf/src/bin/pdm.rs diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs index faa52d8f..3e500098 100644 --- a/embassy-nrf/src/chips/nrf52810.rs +++ b/embassy-nrf/src/chips/nrf52810.rs @@ -128,6 +128,9 @@ embassy_hal_common::peripherals! { // QDEC QDEC, + + // PDM + PDM, } impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs index bbdf1cbe..25c7c0d9 100644 --- a/embassy-nrf/src/chips/nrf52811.rs +++ b/embassy-nrf/src/chips/nrf52811.rs @@ -128,6 +128,9 @@ embassy_hal_common::peripherals! { // QDEC QDEC, + + // PDM + PDM, } impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs index 18b8eda6..2c6276d4 100644 --- a/embassy-nrf/src/chips/nrf52832.rs +++ b/embassy-nrf/src/chips/nrf52832.rs @@ -138,6 +138,9 @@ embassy_hal_common::peripherals! { // QDEC QDEC, + + // PDM + PDM, } impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs index 39a0f93f..3b33907d 100644 --- a/embassy-nrf/src/chips/nrf52833.rs +++ b/embassy-nrf/src/chips/nrf52833.rs @@ -158,6 +158,9 @@ embassy_hal_common::peripherals! { // QDEC QDEC, + + // PDM + PDM, } #[cfg(feature = "nightly")] diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs index e3d8f34a..ae59f8b2 100644 --- a/embassy-nrf/src/chips/nrf52840.rs +++ b/embassy-nrf/src/chips/nrf52840.rs @@ -161,6 +161,9 @@ embassy_hal_common::peripherals! { // TEMP TEMP, + + // PDM + PDM, } #[cfg(feature = "nightly")] diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index f3b3ca0c..20589195 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -103,6 +103,14 @@ pub mod uarte; pub mod usb; #[cfg(not(feature = "_nrf5340"))] pub mod wdt; +#[cfg(any( + feature = "nrf52810", + feature = "nrf52811", + feature = "nrf52832", + feature = "nrf52833", + feature = "nrf52840", +))] +pub mod pdm; // This mod MUST go last, so that it sees all the `impl_foo!` macros #[cfg_attr(feature = "nrf52805", path = "chips/nrf52805.rs")] diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs new file mode 100644 index 00000000..629eab99 --- /dev/null +++ b/embassy-nrf/src/pdm.rs @@ -0,0 +1,185 @@ +#![macro_use] + +use core::sync::atomic::{compiler_fence, Ordering}; +use core::task::Poll; + +use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_util::waitqueue::AtomicWaker; +use futures::future::poll_fn; +use pac::{pdm, PDM}; +use pdm::mode::{EDGE_A, OPERATION_A}; +use fixed::types::I7F1; + +use crate::interrupt::InterruptExt; +use crate::gpio::Pin as GpioPin; +use crate::{interrupt, pac, peripherals, Peripheral}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum Error {} + +/// One-shot and continuous PDM. +pub struct Pdm<'d> { + _p: PeripheralRef<'d, peripherals::PDM>, +} + +static WAKER: AtomicWaker = AtomicWaker::new(); + +/// Used to configure the PDM peripheral. +/// +/// See the `Default` impl for suitable default values. +#[non_exhaustive] +pub struct Config { + /// Clock + /// Clock ratio + /// Channels + pub channels: Channels, + /// Edge to sample on + pub left_edge: Edge, + /// Gain left in dB + pub gain_left: I7F1, + /// Gain right in dB + pub gain_right: I7F1, +} + +impl Default for Config { + /// Default configuration for single channel sampling. + fn default() -> Self { + Self { + channels: Channels::Stereo, + left_edge: Edge::FallingEdge, + gain_left: I7F1::ZERO, + gain_right: I7F1::ZERO, + } + } +} + +/// The state of a continuously running sampler. While it reflects +/// the progress of a sampler, it also signals what should be done +/// next. For example, if the sampler has stopped then the Pdm implementation +/// can then tear down its infrastructure. +#[derive(PartialEq)] +pub enum SamplerState { + Sampled, + Stopped, +} + +impl<'d> Pdm<'d> { + pub fn new( + pdm: impl Peripheral

+ 'd, + irq: impl Peripheral

+ 'd, + data: impl Peripheral

+ 'd, + clock: impl Peripheral

+ 'd, + config: Config, + ) -> Self { + into_ref!(pdm, irq, data, clock); + + let r = unsafe { &*PDM::ptr() }; + + let Config { channels, left_edge, gain_left, gain_right } = config; + + // Configure channels + r.enable.write(|w| w.enable().enabled()); + // TODO: Clock control + r.mode.write(|w| { + w.operation().variant(channels.into()); + w.edge().variant(left_edge.into()); + w + }); + + r.psel.din.write(|w| unsafe { w.bits(data.psel_bits()) }); + r.psel.clk.write(|w| unsafe { w.bits(clock.psel_bits()) }); + + // Disable all events interrupts + r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) }); + + irq.set_handler(Self::on_interrupt); + irq.unpend(); + irq.enable(); + + Self { _p: pdm } + } + + fn on_interrupt(_ctx: *mut ()) { + let r = Self::regs(); + + if r.events_end.read().bits() != 0 { + r.intenclr.write(|w| w.end().clear()); + WAKER.wake(); + } + + if r.events_started.read().bits() != 0 { + r.intenclr.write(|w| w.started().clear()); + WAKER.wake(); + } + } + + fn regs() -> &'static pdm::RegisterBlock { + unsafe { &*PDM::ptr() } + } + + /// One shot sampling. If the PDM is configured for multiple channels, the samples will be interleaved. + pub async fn sample(&mut self, buf: &mut [i16; N]) { + let r = Self::regs(); + + // Set up the DMA + r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(buf.as_mut_ptr() as u32) }); + r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(N as _) }); + + // Reset and enable the end event + r.events_end.reset(); + r.intenset.write(|w| w.end().set()); + + // Don't reorder the start event before the previous writes. Hopefully self + // wouldn't happen anyway. + compiler_fence(Ordering::SeqCst); + + r.tasks_start.write(|w| { w.tasks_start().set_bit() }); + + // Wait for 'end' event. + poll_fn(|cx| { + let r = Self::regs(); + + WAKER.register(cx.waker()); + + if r.events_end.read().bits() != 0 { + r.events_end.reset(); + return Poll::Ready(()); + } + + Poll::Pending + }) + .await; + } +} + +#[derive(Clone, Copy, PartialEq)] +pub enum Edge { + FallingEdge, + RisingEdge, +} + +impl From for EDGE_A { + fn from(edge: Edge) -> Self { + match edge { + Edge::FallingEdge => EDGE_A::LEFTFALLING, + Edge::RisingEdge => EDGE_A::LEFTRISING, + } + } +} + +#[derive(Clone, Copy, PartialEq)] +pub enum Channels { + Stereo, + Mono, +} + +impl From for OPERATION_A { + fn from(ch: Channels) -> Self { + match ch { + Channels::Stereo => OPERATION_A::STEREO, + Channels::Mono => OPERATION_A::MONO, + } + } +} \ No newline at end of file diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index 2fcc3122..673bcfc6 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml @@ -27,6 +27,7 @@ cortex-m-rt = "0.7.0" panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } rand = { version = "0.8.4", default-features = false } +fixed = "1.10.0" embedded-storage = "0.3.0" usbd-hid = "0.5.2" serde = { version = "1.0.136", default-features = false } diff --git a/examples/nrf/src/bin/pdm.rs b/examples/nrf/src/bin/pdm.rs new file mode 100644 index 00000000..d5e90e27 --- /dev/null +++ b/examples/nrf/src/bin/pdm.rs @@ -0,0 +1,34 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nrf::interrupt; +use embassy_nrf::pdm::{Config, Channels, Pdm}; +use embassy_time::{Duration, Timer}; +use fixed::types::I7F1; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_p: Spawner) { + let mut p = embassy_nrf::init(Default::default()); + let mut config = Config::default(); + // Pins are correct for the onboard microphone on the Feather nRF52840 Sense. + config.channels = Channels::Mono; + config.gain_left = I7F1::from_bits(5); // 2.5 dB + let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), &mut p.P0_00, &mut p.P0_01, config); + + loop { + let mut buf = [0; 128]; + pdm.sample(&mut buf).await; + info!( + "{} samples, min {=i16}, max {=i16}, mean {=i16}", + buf.len(), + buf.iter().min().unwrap(), + buf.iter().max().unwrap(), + (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16, + ); + Timer::after(Duration::from_millis(100)).await; + } +} From 530f192acceb5a10c416e1823dc27a749e68b7dc Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sat, 20 Aug 2022 17:08:29 -0400 Subject: [PATCH 002/148] Set gain at runtime --- embassy-nrf/src/pdm.rs | 21 +++++++++++++++++++++ examples/nrf/Cargo.toml | 1 + examples/nrf/src/bin/pdm.rs | 29 +++++++++++++++++++---------- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index 629eab99..b3cc8760 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -88,6 +88,8 @@ impl<'d> Pdm<'d> { w }); + Self::_set_gain(r, gain_left, gain_right); + r.psel.din.write(|w| unsafe { w.bits(data.psel_bits()) }); r.psel.clk.write(|w| unsafe { w.bits(clock.psel_bits()) }); @@ -115,6 +117,18 @@ impl<'d> Pdm<'d> { } } + fn _set_gain(r: &pdm::RegisterBlock, gain_left: I7F1, gain_right: I7F1) { + let gain_left = gain_left.saturating_add(I7F1::from_bits(40)).saturating_to_num::().clamp(0, 0x50); + let gain_right = gain_right.saturating_add(I7F1::from_bits(40)).saturating_to_num::().clamp(0, 0x50); + + r.gainl.write(|w| unsafe { w.gainl().bits(gain_left) }); + r.gainr.write(|w| unsafe { w.gainr().bits(gain_right) }); + } + + pub fn set_gain(&mut self, gain_left: I7F1, gain_right: I7F1) { + Self::_set_gain(Self::regs(), gain_left, gain_right) + } + fn regs() -> &'static pdm::RegisterBlock { unsafe { &*PDM::ptr() } } @@ -154,6 +168,13 @@ impl<'d> Pdm<'d> { } } +impl<'d> Drop for Pdm<'d> { + fn drop(&mut self) { + let r = Self::regs(); + r.enable.write(|w| w.enable().disabled()); + } +} + #[derive(Clone, Copy, PartialEq)] pub enum Edge { FallingEdge, diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index 673bcfc6..d0567ba8 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml @@ -31,3 +31,4 @@ fixed = "1.10.0" embedded-storage = "0.3.0" usbd-hid = "0.5.2" serde = { version = "1.0.136", default-features = false } +num-integer = { version = "0.1.45", default-features = false } diff --git a/examples/nrf/src/bin/pdm.rs b/examples/nrf/src/bin/pdm.rs index d5e90e27..a73d01fb 100644 --- a/examples/nrf/src/bin/pdm.rs +++ b/examples/nrf/src/bin/pdm.rs @@ -8,6 +8,7 @@ use embassy_nrf::interrupt; use embassy_nrf::pdm::{Config, Channels, Pdm}; use embassy_time::{Duration, Timer}; use fixed::types::I7F1; +use num_integer::Roots; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -20,15 +21,23 @@ async fn main(_p: Spawner) { let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), &mut p.P0_00, &mut p.P0_01, config); loop { - let mut buf = [0; 128]; - pdm.sample(&mut buf).await; - info!( - "{} samples, min {=i16}, max {=i16}, mean {=i16}", - buf.len(), - buf.iter().min().unwrap(), - buf.iter().max().unwrap(), - (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16, - ); - Timer::after(Duration::from_millis(100)).await; + for gain in [I7F1::from_num(-20), I7F1::from_num(0), I7F1::from_num(20)] { + pdm.set_gain(gain, gain); + info!("Gain = {} dB", defmt::Debug2Format(&gain)); + for _ in 0..10 { + let mut buf = [0; 128]; + pdm.sample(&mut buf).await; + info!( + "{} samples, min {=i16}, max {=i16}, RMS {=i16}", + buf.len(), + buf.iter().min().unwrap(), + buf.iter().max().unwrap(), + ( + buf.iter().map(|v| i32::from(*v).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) + / buf.len() as i32).sqrt() as i16, + ); + Timer::after(Duration::from_millis(100)).await; + } + } } } From 0963b5f92c9588ab00f556a6c521fad059eac72e Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sat, 20 Aug 2022 17:58:54 -0400 Subject: [PATCH 003/148] Add continuous PDM sampling with example --- embassy-nrf/src/pdm.rs | 118 ++++++++++++++++++++++++- examples/nrf/src/bin/pdm.rs | 3 +- examples/nrf/src/bin/pdm_continuous.rs | 50 +++++++++++ 3 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 examples/nrf/src/bin/pdm_continuous.rs diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index b3cc8760..db4c74af 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -115,6 +115,11 @@ impl<'d> Pdm<'d> { r.intenclr.write(|w| w.started().clear()); WAKER.wake(); } + + if r.events_stopped.read().bits() != 0 { + r.intenclr.write(|w| w.stopped().clear()); + WAKER.wake(); + } } fn _set_gain(r: &pdm::RegisterBlock, gain_left: I7F1, gain_right: I7F1) { @@ -141,15 +146,20 @@ impl<'d> Pdm<'d> { r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(buf.as_mut_ptr() as u32) }); r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(N as _) }); - // Reset and enable the end event + // Reset and enable the events r.events_end.reset(); - r.intenset.write(|w| w.end().set()); + r.events_stopped.reset(); + r.intenset.write(|w| { + w.end().set(); + w.stopped().set(); + w + }); // Don't reorder the start event before the previous writes. Hopefully self // wouldn't happen anyway. compiler_fence(Ordering::SeqCst); - r.tasks_start.write(|w| { w.tasks_start().set_bit() }); + r.tasks_start.write(|w| w.tasks_start().set_bit()); // Wait for 'end' event. poll_fn(|cx| { @@ -158,7 +168,109 @@ impl<'d> Pdm<'d> { WAKER.register(cx.waker()); if r.events_end.read().bits() != 0 { + // END means the whole buffer has been received. r.events_end.reset(); + // Note that the beginning of the buffer might be overwritten before the task fully stops :( + r.tasks_stop.write(|w| w.tasks_stop().set_bit()); + } + + if r.events_stopped.read().bits() != 0 { + r.events_stopped.reset(); + return Poll::Ready(()); + } + + Poll::Pending + }) + .await; + } + + /// Continuous sampling with double buffers. + /// + /// A TIMER and two PPI peripherals are passed in so that precise sampling + /// can be attained. The sampling interval is expressed by selecting a + /// timer clock frequency to use along with a counter threshold to be reached. + /// For example, 1KHz can be achieved using a frequency of 1MHz and a counter + /// threshold of 1000. + /// + /// A sampler closure is provided that receives the buffer of samples, noting + /// that the size of this buffer can be less than the original buffer's size. + /// A command is return from the closure that indicates whether the sampling + /// should continue or stop. + /// + /// NOTE: The time spent within the callback supplied should not exceed the time + /// taken to acquire the samples into a single buffer. You should measure the + /// time taken by the callback and set the sample buffer size accordingly. + /// Exceeding this time can lead to samples becoming dropped. + pub async fn run_task_sampler( + &mut self, + bufs: &mut [[i16; N]; 2], + mut sampler: S, + ) where + S: FnMut(&[i16; N]) -> SamplerState, + { + let r = Self::regs(); + + r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(bufs[0].as_mut_ptr() as u32) }); + r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(N as _) }); + + // Reset and enable the events + r.events_end.reset(); + r.events_started.reset(); + r.events_stopped.reset(); + r.intenset.write(|w| { + w.end().set(); + w.started().set(); + w.stopped().set(); + w + }); + + // Don't reorder the start event before the previous writes. Hopefully self + // wouldn't happen anyway. + compiler_fence(Ordering::SeqCst); + + r.tasks_start.write(|w| { w.tasks_start().set_bit() }); + + let mut current_buffer = 0; + + let mut done = false; + + // Wait for events and complete when the sampler indicates it has had enough. + poll_fn(|cx| { + let r = Self::regs(); + + WAKER.register(cx.waker()); + + if r.events_end.read().bits() != 0 { + compiler_fence(Ordering::SeqCst); + + r.events_end.reset(); + r.intenset.write(|w| w.end().set()); + + if !done { // Discard the last buffer after the user requested a stop. + if sampler(&bufs[current_buffer]) == SamplerState::Sampled { + let next_buffer = 1 - current_buffer; + current_buffer = next_buffer; + } else { + r.tasks_stop.write(|w| w.tasks_stop().set_bit()); + done = true; + }; + }; + } + + if r.events_started.read().bits() != 0 { + r.events_started.reset(); + r.intenset.write(|w| w.started().set()); + + let next_buffer = 1 - current_buffer; + r.sample + .ptr + .write(|w| unsafe { w.sampleptr().bits(bufs[next_buffer].as_mut_ptr() as u32) }); + } + + if r.events_stopped.read().bits() != 0 { + r.events_stopped.reset(); + r.intenset.write(|w| w.stopped().set()); + return Poll::Ready(()); } diff --git a/examples/nrf/src/bin/pdm.rs b/examples/nrf/src/bin/pdm.rs index a73d01fb..85a59a52 100644 --- a/examples/nrf/src/bin/pdm.rs +++ b/examples/nrf/src/bin/pdm.rs @@ -25,7 +25,7 @@ async fn main(_p: Spawner) { pdm.set_gain(gain, gain); info!("Gain = {} dB", defmt::Debug2Format(&gain)); for _ in 0..10 { - let mut buf = [0; 128]; + let mut buf = [0; 1500]; pdm.sample(&mut buf).await; info!( "{} samples, min {=i16}, max {=i16}, RMS {=i16}", @@ -36,6 +36,7 @@ async fn main(_p: Spawner) { buf.iter().map(|v| i32::from(*v).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) / buf.len() as i32).sqrt() as i16, ); + info!("samples = {}", &buf); Timer::after(Duration::from_millis(100)).await; } } diff --git a/examples/nrf/src/bin/pdm_continuous.rs b/examples/nrf/src/bin/pdm_continuous.rs new file mode 100644 index 00000000..e7d1806b --- /dev/null +++ b/examples/nrf/src/bin/pdm_continuous.rs @@ -0,0 +1,50 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nrf::interrupt; +use embassy_nrf::pdm::{Config, Channels, Pdm, SamplerState}; +use embassy_nrf::timer::Frequency; +use fixed::types::I7F1; +use num_integer::Roots; +use {defmt_rtt as _, panic_probe as _}; + +// Demonstrates both continuous sampling and scanning multiple channels driven by a PPI linked timer + +#[embassy_executor::main] +async fn main(_p: Spawner) { + let mut p = embassy_nrf::init(Default::default()); + let mut config = Config::default(); + // Pins are correct for the onboard microphone on the Feather nRF52840 Sense. + config.channels = Channels::Mono; + config.gain_left = I7F1::from_bits(5); // 2.5 dB + let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), &mut p.P0_00, &mut p.P0_01, config); + + let mut bufs = [[0; 500]; 2]; + + pdm + .run_task_sampler( + &mut bufs, + move |buf| { + // NOTE: It is important that the time spent within this callback + // does not exceed the time taken to acquire the 1500 samples we + // have in this example, which would be 10us + 2us per + // sample * 1500 = 18ms. You need to measure the time taken here + // and set the sample buffer size accordingly. Exceeding this + // time can lead to the peripheral re-writing the other buffer. + info!( + "{} samples, min {=i16}, max {=i16}, RMS {=i16}", + buf.len(), + buf.iter().min().unwrap(), + buf.iter().max().unwrap(), + ( + buf.iter().map(|v| i32::from(*v).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) + / buf.len() as i32).sqrt() as i16, + ); + SamplerState::Sampled + }, + ) + .await; +} From 3d26573c6b36c670a170279db49e7adc5e37466b Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sun, 21 Aug 2022 01:44:04 -0400 Subject: [PATCH 004/148] Discard the first N samples due to transients --- embassy-nrf/src/pdm.rs | 22 +++++++++++++++++++--- examples/nrf/src/bin/pdm.rs | 8 +++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index db4c74af..c8375b1e 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -139,7 +139,8 @@ impl<'d> Pdm<'d> { } /// One shot sampling. If the PDM is configured for multiple channels, the samples will be interleaved. - pub async fn sample(&mut self, buf: &mut [i16; N]) { + /// The first samples from the PDM peripheral and microphone usually contain garbage data, so the discard parameter sets the number of complete buffers to discard before returning. + pub async fn sample(&mut self, mut discard: usize, buf: &mut [i16; N]) { let r = Self::regs(); // Set up the DMA @@ -148,9 +149,11 @@ impl<'d> Pdm<'d> { // Reset and enable the events r.events_end.reset(); + r.events_started.reset(); r.events_stopped.reset(); r.intenset.write(|w| { w.end().set(); + w.started().set(); w.stopped().set(); w }); @@ -168,13 +171,26 @@ impl<'d> Pdm<'d> { WAKER.register(cx.waker()); if r.events_end.read().bits() != 0 { + compiler_fence(Ordering::SeqCst); // END means the whole buffer has been received. r.events_end.reset(); - // Note that the beginning of the buffer might be overwritten before the task fully stops :( - r.tasks_stop.write(|w| w.tasks_stop().set_bit()); + r.intenset.write(|w| w.end().set()); + + if discard > 0 { + discard -= 1; + } else { + // Note that the beginning of the buffer might be overwritten before the task fully stops :( + r.tasks_stop.write(|w| w.tasks_stop().set_bit()); + } + } + + if r.events_started.read().bits() != 0 { + compiler_fence(Ordering::SeqCst); + r.events_started.reset(); } if r.events_stopped.read().bits() != 0 { + compiler_fence(Ordering::SeqCst); r.events_stopped.reset(); return Poll::Ready(()); } diff --git a/examples/nrf/src/bin/pdm.rs b/examples/nrf/src/bin/pdm.rs index 85a59a52..605eca59 100644 --- a/examples/nrf/src/bin/pdm.rs +++ b/examples/nrf/src/bin/pdm.rs @@ -26,14 +26,16 @@ async fn main(_p: Spawner) { info!("Gain = {} dB", defmt::Debug2Format(&gain)); for _ in 0..10 { let mut buf = [0; 1500]; - pdm.sample(&mut buf).await; + pdm.sample(5, &mut buf).await; + let mean = (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16; info!( - "{} samples, min {=i16}, max {=i16}, RMS {=i16}", + "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}", buf.len(), buf.iter().min().unwrap(), buf.iter().max().unwrap(), + mean, ( - buf.iter().map(|v| i32::from(*v).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) + buf.iter().map(|v| i32::from(*v - mean).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) / buf.len() as i32).sqrt() as i16, ); info!("samples = {}", &buf); From 029713eca0e6c4a17283891de77c69f27bbf1a54 Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sun, 21 Aug 2022 02:04:11 -0400 Subject: [PATCH 005/148] Stop PDM sampling when future is dropped --- embassy-nrf/src/pdm.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index c8375b1e..6a070e7b 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -4,6 +4,7 @@ use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_common::drop::OnDrop; use embassy_util::waitqueue::AtomicWaker; use futures::future::poll_fn; use pac::{pdm, PDM}; @@ -149,11 +150,9 @@ impl<'d> Pdm<'d> { // Reset and enable the events r.events_end.reset(); - r.events_started.reset(); r.events_stopped.reset(); r.intenset.write(|w| { w.end().set(); - w.started().set(); w.stopped().set(); w }); @@ -164,6 +163,12 @@ impl<'d> Pdm<'d> { r.tasks_start.write(|w| w.tasks_start().set_bit()); + let ondrop = OnDrop::new(|| { + r.tasks_stop.write(|w| w.tasks_stop().set_bit()); + // N.B. It would be better if this were async, but Drop only support sync code. + while r.events_stopped.read().bits() != 0 {} + }); + // Wait for 'end' event. poll_fn(|cx| { let r = Self::regs(); @@ -183,21 +188,14 @@ impl<'d> Pdm<'d> { r.tasks_stop.write(|w| w.tasks_stop().set_bit()); } } - - if r.events_started.read().bits() != 0 { - compiler_fence(Ordering::SeqCst); - r.events_started.reset(); - } - if r.events_stopped.read().bits() != 0 { - compiler_fence(Ordering::SeqCst); - r.events_stopped.reset(); return Poll::Ready(()); } Poll::Pending }) .await; + ondrop.defuse(); } /// Continuous sampling with double buffers. @@ -250,6 +248,12 @@ impl<'d> Pdm<'d> { let mut done = false; + let ondrop = OnDrop::new(|| { + r.tasks_stop.write(|w| w.tasks_stop().set_bit()); + // N.B. It would be better if this were async, but Drop only support sync code. + while r.events_stopped.read().bits() != 0 {} + }); + // Wait for events and complete when the sampler indicates it has had enough. poll_fn(|cx| { let r = Self::regs(); @@ -284,15 +288,13 @@ impl<'d> Pdm<'d> { } if r.events_stopped.read().bits() != 0 { - r.events_stopped.reset(); - r.intenset.write(|w| w.stopped().set()); - return Poll::Ready(()); } Poll::Pending }) .await; + ondrop.defuse(); } } From ed97e61dbecc636c3cc9f67778d4b7eb48cff893 Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sun, 21 Aug 2022 02:16:26 -0400 Subject: [PATCH 006/148] PDM clock frequency control --- embassy-nrf/src/pdm.rs | 13 ++++++++++--- examples/nrf/src/bin/pdm_continuous.rs | 13 ++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index 6a070e7b..b58a0e97 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -9,6 +9,8 @@ use embassy_util::waitqueue::AtomicWaker; use futures::future::poll_fn; use pac::{pdm, PDM}; use pdm::mode::{EDGE_A, OPERATION_A}; +pub use pdm::pdmclkctrl::FREQ_A as Frequency; +pub use pdm::ratio::RATIO_A as Ratio; use fixed::types::I7F1; use crate::interrupt::InterruptExt; @@ -32,8 +34,10 @@ static WAKER: AtomicWaker = AtomicWaker::new(); /// See the `Default` impl for suitable default values. #[non_exhaustive] pub struct Config { - /// Clock + /// Clock frequency + pub frequency: Frequency, /// Clock ratio + pub ratio: Ratio, /// Channels pub channels: Channels, /// Edge to sample on @@ -48,6 +52,8 @@ impl Default for Config { /// Default configuration for single channel sampling. fn default() -> Self { Self { + frequency: Frequency::DEFAULT, + ratio: Ratio::RATIO80, channels: Channels::Stereo, left_edge: Edge::FallingEdge, gain_left: I7F1::ZERO, @@ -78,11 +84,12 @@ impl<'d> Pdm<'d> { let r = unsafe { &*PDM::ptr() }; - let Config { channels, left_edge, gain_left, gain_right } = config; + let Config { frequency, ratio, channels, left_edge, gain_left, gain_right } = config; // Configure channels r.enable.write(|w| w.enable().enabled()); - // TODO: Clock control + r.pdmclkctrl.write(|w| w.freq().variant(frequency)); + r.ratio.write(|w| w.ratio().variant(ratio)); r.mode.write(|w| { w.operation().variant(channels.into()); w.edge().variant(left_edge.into()); diff --git a/examples/nrf/src/bin/pdm_continuous.rs b/examples/nrf/src/bin/pdm_continuous.rs index e7d1806b..33ba1e27 100644 --- a/examples/nrf/src/bin/pdm_continuous.rs +++ b/examples/nrf/src/bin/pdm_continuous.rs @@ -5,8 +5,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_nrf::interrupt; -use embassy_nrf::pdm::{Config, Channels, Pdm, SamplerState}; -use embassy_nrf::timer::Frequency; +use embassy_nrf::pdm::{Config, Channels, Pdm, SamplerState, Frequency, Ratio}; use fixed::types::I7F1; use num_integer::Roots; use {defmt_rtt as _, panic_probe as _}; @@ -18,11 +17,13 @@ async fn main(_p: Spawner) { let mut p = embassy_nrf::init(Default::default()); let mut config = Config::default(); // Pins are correct for the onboard microphone on the Feather nRF52840 Sense. + config.frequency = Frequency::_1280K; // 16 kHz sample rate + config.ratio = Ratio::RATIO80; config.channels = Channels::Mono; config.gain_left = I7F1::from_bits(5); // 2.5 dB let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), &mut p.P0_00, &mut p.P0_01, config); - let mut bufs = [[0; 500]; 2]; + let mut bufs = [[0; 1024]; 2]; pdm .run_task_sampler( @@ -34,13 +35,15 @@ async fn main(_p: Spawner) { // sample * 1500 = 18ms. You need to measure the time taken here // and set the sample buffer size accordingly. Exceeding this // time can lead to the peripheral re-writing the other buffer. + let mean = (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16; info!( - "{} samples, min {=i16}, max {=i16}, RMS {=i16}", + "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}", buf.len(), buf.iter().min().unwrap(), buf.iter().max().unwrap(), + mean, ( - buf.iter().map(|v| i32::from(*v).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) + buf.iter().map(|v| i32::from(*v - mean).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) / buf.len() as i32).sqrt() as i16, ); SamplerState::Sampled From 64154fec8cd7497992ef0d93f319b98215b8a84e Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sun, 21 Aug 2022 02:43:13 -0400 Subject: [PATCH 007/148] Demonstrate FFT in example --- examples/nrf/Cargo.toml | 1 + examples/nrf/src/bin/pdm_continuous.rs | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index d0567ba8..876dcf73 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml @@ -32,3 +32,4 @@ embedded-storage = "0.3.0" usbd-hid = "0.5.2" serde = { version = "1.0.136", default-features = false } num-integer = { version = "0.1.45", default-features = false } +microfft = "0.5.0" diff --git a/examples/nrf/src/bin/pdm_continuous.rs b/examples/nrf/src/bin/pdm_continuous.rs index 33ba1e27..e78bc40d 100644 --- a/examples/nrf/src/bin/pdm_continuous.rs +++ b/examples/nrf/src/bin/pdm_continuous.rs @@ -3,11 +3,13 @@ #![feature(type_alias_impl_trait)] use defmt::info; +use core::cmp::Ordering; use embassy_executor::Spawner; use embassy_nrf::interrupt; use embassy_nrf::pdm::{Config, Channels, Pdm, SamplerState, Frequency, Ratio}; use fixed::types::I7F1; use num_integer::Roots; +use microfft::real::rfft_1024; use {defmt_rtt as _, panic_probe as _}; // Demonstrates both continuous sampling and scanning multiple channels driven by a PPI linked timer @@ -36,8 +38,10 @@ async fn main(_p: Spawner) { // and set the sample buffer size accordingly. Exceeding this // time can lead to the peripheral re-writing the other buffer. let mean = (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16; + let (peak_freq_index, peak_mag) = fft_peak_freq(&buf); + let peak_freq = peak_freq_index * 16000 / buf.len(); info!( - "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}", + "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}, peak {} @ {} Hz", buf.len(), buf.iter().min().unwrap(), buf.iter().max().unwrap(), @@ -45,9 +49,27 @@ async fn main(_p: Spawner) { ( buf.iter().map(|v| i32::from(*v - mean).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) / buf.len() as i32).sqrt() as i16, + peak_mag, peak_freq, ); SamplerState::Sampled }, ) .await; } + +fn fft_peak_freq(input: &[i16; 1024]) -> (usize, u32) { + let mut f = [0f32; 1024]; + for i in 0..input.len() { + f[i] = (input[i] as f32) / 32768.0; + } + // N.B. rfft_1024 does the FFT in-place so result is actually also a reference to f. + let result = rfft_1024(&mut f); + result[0].im = 0.0; + + result + .iter() + .map(|c| ((c.norm_sqr()*32768.0) as u32).sqrt()) + .enumerate() + .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Equal)) + .unwrap() +} \ No newline at end of file From 14eae9ca06f63a69ccc29d5fd9e1dec3848a3e98 Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sun, 21 Aug 2022 12:40:51 -0400 Subject: [PATCH 008/148] Optimize pdm_continuous example --- examples/nrf/src/bin/pdm_continuous.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/nrf/src/bin/pdm_continuous.rs b/examples/nrf/src/bin/pdm_continuous.rs index e78bc40d..284a68af 100644 --- a/examples/nrf/src/bin/pdm_continuous.rs +++ b/examples/nrf/src/bin/pdm_continuous.rs @@ -68,8 +68,9 @@ fn fft_peak_freq(input: &[i16; 1024]) -> (usize, u32) { result .iter() - .map(|c| ((c.norm_sqr()*32768.0) as u32).sqrt()) + .map(|c| c.norm_sqr()) .enumerate() .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Equal)) + .map(|(i, v)| (i, ((v*32768.0) as u32).sqrt())) .unwrap() -} \ No newline at end of file +} From d896f80405aa8963877049ed999e4aba25d6e2bb Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Tue, 23 Aug 2022 23:02:48 -0400 Subject: [PATCH 009/148] util -> sync rename --- embassy-nrf/src/pdm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index b58a0e97..c2c54fba 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -5,7 +5,7 @@ use core::task::Poll; use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::drop::OnDrop; -use embassy_util::waitqueue::AtomicWaker; +use embassy_sync::waitqueue::AtomicWaker; use futures::future::poll_fn; use pac::{pdm, PDM}; use pdm::mode::{EDGE_A, OPERATION_A}; From 5ecf9ec7bcd785555563d8f5006fd24414bbc17f Mon Sep 17 00:00:00 2001 From: Philipp Scheff Date: Thu, 22 Jun 2023 17:17:51 +0200 Subject: [PATCH 010/148] split can --- embassy-stm32/src/can/bxcan.rs | 101 +++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 16 deletions(-) diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index 88eef528..7b664a11 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs @@ -2,7 +2,7 @@ use core::future::poll_fn; use core::marker::PhantomData; use core::ops::{Deref, DerefMut}; use core::task::Poll; - +use core::cell::RefCell; pub use bxcan; use bxcan::{Data, ExtendedId, Frame, Id, StandardId}; use embassy_hal_common::{into_ref, PeripheralRef}; @@ -72,7 +72,7 @@ impl interrupt::typelevel::Handler for SceInterrup } pub struct Can<'d, T: Instance> { - can: bxcan::Can>, + pub can: RefCell>>, } #[derive(Debug)] @@ -147,19 +147,20 @@ impl<'d, T: Instance> Can<'d, T> { tx.set_as_af(tx.af_num(), AFType::OutputPushPull); let can = bxcan::Can::builder(BxcanInstance(peri)).leave_disabled(); - Self { can } + let can_ref_cell = RefCell::new(can); + Self { can: can_ref_cell } } pub fn set_bitrate(&mut self, bitrate: u32) { let bit_timing = Self::calc_bxcan_timings(T::frequency(), bitrate).unwrap(); - self.can.modify_config().set_bit_timing(bit_timing).leave_disabled(); + self.can.borrow_mut().modify_config().set_bit_timing(bit_timing).leave_disabled(); } /// Queues the message to be sent but exerts backpressure pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { poll_fn(|cx| { T::state().tx_waker.register(cx.waker()); - if let Ok(status) = self.can.transmit(frame) { + if let Ok(status) = self.can.borrow_mut().transmit(frame) { return Poll::Ready(status); } @@ -341,6 +342,74 @@ impl<'d, T: Instance> Can<'d, T> { // Pack into BTR register values Some((sjw - 1) << 24 | (bs1 as u32 - 1) << 16 | (bs2 as u32 - 1) << 20 | (prescaler as u32 - 1)) } + + pub fn split<'c>(&'c self) -> (CanTx<'c, 'd, T>, CanRx<'c, 'd, T>) { + (CanTx { can: &self.can }, CanRx { can: &self.can }) + } +} + +pub struct CanTx<'c, 'd, T: Instance> { + can: &'c RefCell>>, +} + +impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { + pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { + poll_fn(|cx| { + T::state().tx_waker.register(cx.waker()); + if let Ok(status) = self.can.borrow_mut().transmit(frame) { + return Poll::Ready(status); + } + + Poll::Pending + }) + .await + } + + pub async fn flush(&self, mb: bxcan::Mailbox) { + poll_fn(|cx| { + T::state().tx_waker.register(cx.waker()); + if T::regs().tsr().read().tme(mb.index()) { + return Poll::Ready(()); + } + + Poll::Pending + }) + .await; + } +} + +pub struct CanRx<'c, 'd, T: Instance> { + can: &'c RefCell>>, +} + +impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> { + pub async fn read(&mut self) -> Result<(u16, bxcan::Frame), BusError> { + poll_fn(|cx| { + T::state().err_waker.register(cx.waker()); + if let Poll::Ready((time, frame)) = T::state().rx_queue.recv().poll_unpin(cx) { + return Poll::Ready(Ok((time, frame))); + } else if let Some(err) = self.curr_error() { + return Poll::Ready(Err(err)); + } + + Poll::Pending + }) + .await + } + + fn curr_error(&self) -> Option { + let err = { T::regs().esr().read() }; + if err.boff() { + return Some(BusError::BusOff); + } else if err.epvf() { + return Some(BusError::BusPassive); + } else if err.ewgf() { + return Some(BusError::BusWarning); + } else if let Some(err) = err.lec().into_bus_err() { + return Some(err); + } + None + } } enum RxFifo { @@ -357,19 +426,19 @@ impl<'d, T: Instance> Drop for Can<'d, T> { } } -impl<'d, T: Instance> Deref for Can<'d, T> { - type Target = bxcan::Can>; +// impl<'d, T: Instance> Deref for Can<'d, T> { +// type Target = bxcan::Can>; - fn deref(&self) -> &Self::Target { - &self.can - } -} +// fn deref(&self) -> &Self::Target { +// self.can.borrow() +// } +// } -impl<'d, T: Instance> DerefMut for Can<'d, T> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.can - } -} +// impl<'d, T: Instance> DerefMut for Can<'d, T> { +// fn deref_mut(&mut self) -> &mut Self::Target { +// self.can.borrow_mut() +// } +// } pub(crate) mod sealed { use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; From f47a148f51c7c0de52a1c202fefe6f863c669854 Mon Sep 17 00:00:00 2001 From: Philipp Scheff Date: Thu, 22 Jun 2023 17:18:55 +0200 Subject: [PATCH 011/148] add stm32f7 can example --- examples/stm32f7/src/bin/can.rs | 63 +++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 examples/stm32f7/src/bin/can.rs diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs new file mode 100644 index 00000000..cf027cc3 --- /dev/null +++ b/examples/stm32f7/src/bin/can.rs @@ -0,0 +1,63 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use core::borrow::BorrowMut; +use core::borrow::Borrow; +use cortex_m_rt::entry; +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::bind_interrupts; +use embassy_stm32::can::bxcan::filter::Mask32; +use embassy_stm32::can::bxcan::{Fifo, Frame, StandardId, Data}; +use embassy_stm32::can::{Can,CanTx,CanRx, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler}; +use embassy_stm32::gpio::{Input, Pull}; +use embassy_stm32::peripherals::CAN3; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + CAN3_RX0 => Rx0InterruptHandler; + CAN3_RX1 => Rx1InterruptHandler; + CAN3_SCE => SceInterruptHandler; + CAN3_TX => TxInterruptHandler; +}); + +#[embassy_executor::task] +pub async fn send_can_message(tx: &'static mut CanTx<'static, 'static, CAN3>) { + loop { + let frame = Frame::new_data(unwrap!(StandardId::new(0 as _)), [0]); + tx.write(&frame).await; + embassy_time::Timer::after(embassy_time::Duration::from_secs(1)).await; + } +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + info!("Hello World!"); + + let mut p = embassy_stm32::init(Default::default()); + + // The next two lines are a workaround for testing without transceiver. + // To synchronise to the bus the RX input needs to see a high level. + // Use `mem::forget()` to release the borrow on the pin but keep the + // pull-up resistor enabled. + let rx_pin = Input::new(&mut p.PA15, Pull::Up); + core::mem::forget(rx_pin); + + let CAN: &'static mut Can<'static,CAN3> = static_cell::make_static!(Can::new(p.CAN3, p.PA8, p.PA15, Irqs)); + CAN.can.borrow_mut().modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); + + CAN.can.borrow_mut() + .modify_config() + .set_bit_timing(0x001c0001) // http://www.bittiming.can-wiki.info/ + .enable(); + + let (tx, mut rx) = CAN.split(); + let TX: &'static mut CanTx<'static, 'static, CAN3> = static_cell::make_static!(tx); + spawner.spawn(send_can_message(TX)).unwrap(); + + loop { + let frame = rx.read().await.unwrap(); + println!("Received: {:?}", frame); + } +} From 76a334bd7c402f530825352b9c12f2a6d749a42c Mon Sep 17 00:00:00 2001 From: Philipp Scheff Date: Thu, 22 Jun 2023 17:47:58 +0200 Subject: [PATCH 012/148] add as_mut & set loopback true in example --- examples/stm32f7/src/bin/can.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs index cf027cc3..d821039c 100644 --- a/examples/stm32f7/src/bin/can.rs +++ b/examples/stm32f7/src/bin/can.rs @@ -45,14 +45,16 @@ async fn main(spawner: Spawner) { core::mem::forget(rx_pin); let CAN: &'static mut Can<'static,CAN3> = static_cell::make_static!(Can::new(p.CAN3, p.PA8, p.PA15, Irqs)); - CAN.can.borrow_mut().modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); + CAN.as_mut().modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); - CAN.can.borrow_mut() + CAN.as_mut() .modify_config() .set_bit_timing(0x001c0001) // http://www.bittiming.can-wiki.info/ + .set_loopback(true) .enable(); let (tx, mut rx) = CAN.split(); + let TX: &'static mut CanTx<'static, 'static, CAN3> = static_cell::make_static!(tx); spawner.spawn(send_can_message(TX)).unwrap(); From 89fbb02979c0abfac99b32e3676c140055f31c1e Mon Sep 17 00:00:00 2001 From: Philipp Scheff Date: Thu, 22 Jun 2023 17:49:33 +0200 Subject: [PATCH 013/148] add as_mut --- embassy-stm32/src/can/bxcan.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index 7b664a11..4afbb568 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs @@ -2,7 +2,9 @@ use core::future::poll_fn; use core::marker::PhantomData; use core::ops::{Deref, DerefMut}; use core::task::Poll; +use core::cell::RefMut; use core::cell::RefCell; + pub use bxcan; use bxcan::{Data, ExtendedId, Frame, Id, StandardId}; use embassy_hal_common::{into_ref, PeripheralRef}; @@ -346,6 +348,10 @@ impl<'d, T: Instance> Can<'d, T> { pub fn split<'c>(&'c self) -> (CanTx<'c, 'd, T>, CanRx<'c, 'd, T>) { (CanTx { can: &self.can }, CanRx { can: &self.can }) } + + pub fn as_mut(&self) -> RefMut<'_, bxcan::Can>> { + self.can.borrow_mut() + } } pub struct CanTx<'c, 'd, T: Instance> { From 24e186e6849223ee076e0fabdfed07d2cd7f7baf Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 29 Jun 2023 18:09:26 +0200 Subject: [PATCH 014/148] feature(1354): Added lifetimes to Event + --- embassy-nrf/src/ppi/mod.rs | 29 ++++++++++++++++++----------- embassy-nrf/src/ppi/ppi.rs | 4 ++-- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs index 76757a24..f6771c2a 100644 --- a/embassy-nrf/src/ppi/mod.rs +++ b/embassy-nrf/src/ppi/mod.rs @@ -15,6 +15,7 @@ //! many tasks and events, but any single task or event can only be coupled with one channel. //! +use core::marker::PhantomData; use core::ptr::NonNull; use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; @@ -125,16 +126,16 @@ const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::(); /// When a task is subscribed to a PPI channel, it will run when the channel is triggered by /// a published event. #[derive(PartialEq, Eq, Clone, Copy)] -pub struct Task(NonNull); +pub struct Task<'d>(NonNull, PhantomData<&'d ()>); -impl Task { +impl<'d> Task<'_> { /// Create a new `Task` from a task register pointer /// /// # Safety /// /// `ptr` must be a pointer to a valid `TASKS_*` register from an nRF peripheral. pub unsafe fn new_unchecked(ptr: NonNull) -> Self { - Self(ptr) + Self(ptr, PhantomData) } /// Triggers this task. @@ -143,7 +144,10 @@ impl Task { } pub(crate) fn from_reg(reg: &T) -> Self { - Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) + Self( + unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }, + PhantomData, + ) } /// Address of subscription register for this task. @@ -156,26 +160,29 @@ impl Task { /// # Safety /// /// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core. -unsafe impl Send for Task {} +unsafe impl Send for Task<'_> {} /// Represents an event that a peripheral can publish. /// /// An event can be set to publish on a PPI channel when the event happens. #[derive(PartialEq, Eq, Clone, Copy)] -pub struct Event(NonNull); +pub struct Event<'d>(NonNull, PhantomData<&'d ()>); -impl Event { +impl<'d> Event<'_> { /// Create a new `Event` from an event register pointer /// /// # Safety /// /// `ptr` must be a pointer to a valid `EVENTS_*` register from an nRF peripheral. pub unsafe fn new_unchecked(ptr: NonNull) -> Self { - Self(ptr) + Self(ptr, PhantomData) } - pub(crate) fn from_reg(reg: &T) -> Self { - Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) + pub(crate) fn from_reg(reg: &'d T) -> Self { + Self( + unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }, + PhantomData, + ) } /// Describes whether this Event is currently in a triggered state. @@ -198,7 +205,7 @@ impl Event { /// # Safety /// /// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core. -unsafe impl Send for Event {} +unsafe impl Send for Event<'_> {} // ====================== // traits diff --git a/embassy-nrf/src/ppi/ppi.rs b/embassy-nrf/src/ppi/ppi.rs index f1eeaee1..6e8a669d 100644 --- a/embassy-nrf/src/ppi/ppi.rs +++ b/embassy-nrf/src/ppi/ppi.rs @@ -3,12 +3,12 @@ use embassy_hal_common::into_ref; use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task}; use crate::{pac, Peripheral}; -impl Task { +impl<'d> Task<'_> { fn reg_val(&self) -> u32 { self.0.as_ptr() as _ } } -impl Event { +impl<'d> Event<'_> { fn reg_val(&self) -> u32 { self.0.as_ptr() as _ } From fef338f5c2d21ad1f45247579b27ffdf33f1096f Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 29 Jun 2023 18:13:46 +0200 Subject: [PATCH 015/148] Lifetime groups --- embassy-nrf/src/ppi/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs index f6771c2a..9092529a 100644 --- a/embassy-nrf/src/ppi/mod.rs +++ b/embassy-nrf/src/ppi/mod.rs @@ -31,9 +31,9 @@ pub(crate) use _version::*; pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> { ch: PeripheralRef<'d, C>, #[cfg(feature = "_dppi")] - events: [Event; EVENT_COUNT], + events: [Event<'d>; EVENT_COUNT], #[cfg(feature = "_dppi")] - tasks: [Task; TASK_COUNT], + tasks: [Task<'d>; TASK_COUNT], } /// PPI channel group driver. From 2432cece38750220c04fe692d7153d1776220222 Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 29 Jun 2023 18:36:12 +0200 Subject: [PATCH 016/148] Lifetimes in dppi --- embassy-nrf/src/ppi/dppi.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-nrf/src/ppi/dppi.rs b/embassy-nrf/src/ppi/dppi.rs index 3a1e7f17..36c1eb8e 100644 --- a/embassy-nrf/src/ppi/dppi.rs +++ b/embassy-nrf/src/ppi/dppi.rs @@ -30,8 +30,8 @@ impl<'d, C: ConfigurableChannel, const EVENT_COUNT: usize, const TASK_COUNT: usi /// Configure a DPPI channel to trigger all `tasks` when any of the `events` fires. pub fn new_many_to_many( ch: impl Peripheral

+ 'd, - events: [Event; EVENT_COUNT], - tasks: [Task; TASK_COUNT], + events: [Event<'d>; EVENT_COUNT], + tasks: [Task<'d>; TASK_COUNT], ) -> Self { into_ref!(ch); From d6fde756a8c5f01e2557165fd2bba457143a3586 Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 30 Jun 2023 11:32:11 +0200 Subject: [PATCH 017/148] Build failures --- embassy-nrf/src/ppi/dppi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-nrf/src/ppi/dppi.rs b/embassy-nrf/src/ppi/dppi.rs index 36c1eb8e..af226745 100644 --- a/embassy-nrf/src/ppi/dppi.rs +++ b/embassy-nrf/src/ppi/dppi.rs @@ -20,7 +20,7 @@ impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { /// Configure PPI channel to trigger both `task1` and `task2` on `event`. pub fn new_one_to_two(ch: impl Peripheral

+ 'd, event: Event, task1: Task, task2: Task) -> Self { - Ppi::new_many_to_many(ch, [event], [task1, task2]) + Ppi<'d>::new_many_to_many(ch, [event], [task1, task2]) } } From 4d23ea554b73f377c1a2c2aca15c4284b188231c Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 30 Jun 2023 11:34:13 +0200 Subject: [PATCH 018/148] Build failures --- embassy-nrf/src/ppi/dppi.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-nrf/src/ppi/dppi.rs b/embassy-nrf/src/ppi/dppi.rs index af226745..c0d6f228 100644 --- a/embassy-nrf/src/ppi/dppi.rs +++ b/embassy-nrf/src/ppi/dppi.rs @@ -19,8 +19,8 @@ impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { /// Configure PPI channel to trigger both `task1` and `task2` on `event`. - pub fn new_one_to_two(ch: impl Peripheral

+ 'd, event: Event, task1: Task, task2: Task) -> Self { - Ppi<'d>::new_many_to_many(ch, [event], [task1, task2]) + pub fn new_one_to_two(ch: impl Peripheral

+ 'd, event: Event<'d>, task1: Task<'d>, task2: Task<'d>) -> Self { + Ppi::new_many_to_many(ch, [event], [task1, task2]) } } From c69f2929c0702701d49b3cd9dcc14d5a6664f5dc Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 30 Jun 2023 11:37:53 +0200 Subject: [PATCH 019/148] Build failures --- embassy-nrf/src/ppi/dppi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-nrf/src/ppi/dppi.rs b/embassy-nrf/src/ppi/dppi.rs index c0d6f228..40ccb2f0 100644 --- a/embassy-nrf/src/ppi/dppi.rs +++ b/embassy-nrf/src/ppi/dppi.rs @@ -12,7 +12,7 @@ pub(crate) fn regs() -> &'static pac::dppic::RegisterBlock { impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { /// Configure PPI channel to trigger `task` on `event`. - pub fn new_one_to_one(ch: impl Peripheral

+ 'd, event: Event, task: Task) -> Self { + pub fn new_one_to_one(ch: impl Peripheral

+ 'd, event: Event<'d>, task: Task<'d>) -> Self { Ppi::new_many_to_many(ch, [event], [task]) } } From 81cbb0fc322c8dd23128a28e0500df1f185e1067 Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 30 Jun 2023 11:47:20 +0200 Subject: [PATCH 020/148] Attempt to fix certain borrowing rule issues --- embassy-nrf/src/buffered_uarte.rs | 4 +++- embassy-nrf/src/saadc.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 9bc1c1e7..c1300d7e 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -352,11 +352,13 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { s.rx_ppi_ch.store(ppi_ch2.number() as u8, Ordering::Relaxed); let mut ppi_group = PpiGroup::new(ppi_group); + let ppi_group_channel_disable_all_task = ppi_group.task_disable_all(); + let mut ppi_ch2 = Ppi::new_one_to_two( ppi_ch2, Event::from_reg(&r.events_endrx), Task::from_reg(&r.tasks_startrx), - ppi_group.task_disable_all(), + ppi_group_channel_disable_all_task ); ppi_ch2.disable(); ppi_group.add_channel(&ppi_ch2); diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs index cf3fb999..b6984b0f 100644 --- a/embassy-nrf/src/saadc.rs +++ b/embassy-nrf/src/saadc.rs @@ -320,7 +320,9 @@ impl<'d, const N: usize> Saadc<'d, N> { timer.cc(0).write(sample_counter); timer.cc(0).short_compare_clear(); - let mut sample_ppi = Ppi::new_one_to_one(ppi_ch2, timer.cc(0).event_compare(), Task::from_reg(&r.tasks_sample)); + let compare_event = timer.cc(0).event_compare(); + + let mut sample_ppi = Ppi::new_one_to_one(ppi_ch2, compare_event, Task::from_reg(&r.tasks_sample)); timer.start(); From bca2c549482c05954b20021ec976609bb607eed3 Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 30 Jun 2023 11:50:27 +0200 Subject: [PATCH 021/148] Adjusted build issue --- embassy-nrf/src/saadc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs index b6984b0f..23292924 100644 --- a/embassy-nrf/src/saadc.rs +++ b/embassy-nrf/src/saadc.rs @@ -320,9 +320,9 @@ impl<'d, const N: usize> Saadc<'d, N> { timer.cc(0).write(sample_counter); timer.cc(0).short_compare_clear(); - let compare_event = timer.cc(0).event_compare(); + let timer_cc = timer.cc(0); - let mut sample_ppi = Ppi::new_one_to_one(ppi_ch2, compare_event, Task::from_reg(&r.tasks_sample)); + let mut sample_ppi = Ppi::new_one_to_one(ppi_ch2, timer_cc.event_compare(), Task::from_reg(&r.tasks_sample)); timer.start(); From 93caf97a04d1383ddeb11cff51b3ca34107a45c8 Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 30 Jun 2023 11:54:37 +0200 Subject: [PATCH 022/148] Formatting stuff --- embassy-nrf/src/buffered_uarte.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index c1300d7e..8fc3b4b9 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -352,13 +352,13 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { s.rx_ppi_ch.store(ppi_ch2.number() as u8, Ordering::Relaxed); let mut ppi_group = PpiGroup::new(ppi_group); - let ppi_group_channel_disable_all_task = ppi_group.task_disable_all(); + let ppi_group_channel_disable_all_task = ppi_group.task_disable_all(); let mut ppi_ch2 = Ppi::new_one_to_two( ppi_ch2, Event::from_reg(&r.events_endrx), Task::from_reg(&r.tasks_startrx), - ppi_group_channel_disable_all_task + ppi_group_channel_disable_all_task, ); ppi_ch2.disable(); ppi_group.add_channel(&ppi_ch2); From d372df7ddb381571fd2964e32b486b6d1cd1ad03 Mon Sep 17 00:00:00 2001 From: Mathias Date: Sat, 1 Jul 2023 12:16:23 +0200 Subject: [PATCH 023/148] L4: Switch to MSI to prevent problems with PLL configuration, and enable power to AHB bus clock to allow RTC to run --- embassy-stm32/src/rcc/l4.rs | 23 +++++++++++++++ examples/stm32l4/src/bin/rtc.rs | 50 +++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 examples/stm32l4/src/bin/rtc.rs diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index f8c1a6e0..f7f3b904 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs @@ -1,6 +1,7 @@ use core::marker::PhantomData; use embassy_hal_common::into_ref; +use stm32_metapac::rcc::regs::Cfgr; use stm32_metapac::rcc::vals::{Lsedrv, Mcopre, Mcosel}; use crate::gpio::sealed::AFType; @@ -439,6 +440,26 @@ impl<'d, T: McoInstance> Mco<'d, T> { } pub(crate) unsafe fn init(config: Config) { + // Switch to MSI to prevent problems with PLL configuration. + if !RCC.cr().read().msion() { + // Turn on MSI and configure it to 4MHz. + RCC.cr().modify(|w| { + w.set_msirgsel(true); // MSI Range is provided by MSIRANGE[3:0]. + w.set_msirange(MSIRange::default().into()); + w.set_msipllen(false); + w.set_msion(true) + }); + + // Wait until MSI is running + while !RCC.cr().read().msirdy() {} + } + if RCC.cfgr().read().sws() != Sw::MSI { + // Set MSI as a clock source, reset prescalers. + RCC.cfgr().write_value(Cfgr::default()); + // Wait for clock switch status bits to change. + while RCC.cfgr().read().sws() != Sw::MSI {} + } + match config.rtc_mux { RtcClockSource::LSE32 => { // 1. Unlock the backup domain @@ -660,6 +681,8 @@ pub(crate) unsafe fn init(config: Config) { } }; + RCC.apb1enr1().modify(|w| w.set_pwren(true)); + set_freqs(Clocks { sys: Hertz(sys_clk), ahb1: Hertz(ahb_freq), diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs new file mode 100644 index 00000000..0de70895 --- /dev/null +++ b/examples/stm32l4/src/bin/rtc.rs @@ -0,0 +1,50 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use chrono::{NaiveDate, NaiveDateTime}; +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::rcc::{self, ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; +use embassy_stm32::rtc::{Rtc, RtcConfig}; +use embassy_stm32::time::Hertz; +use embassy_stm32::Config; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = { + let mut config = Config::default(); + config.rcc.mux = ClockSrc::PLL( + PLLSource::HSE(Hertz::mhz(8)), + PLLClkDiv::Div2, + PLLSrcDiv::Div1, + PLLMul::Mul20, + None, + ); + config.rcc.rtc_mux = rcc::RtcClockSource::LSE32; + 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().clock_config(embassy_stm32::rtc::RtcClockSource::LSE), + ); + info!("Got RTC! {:?}", now.timestamp()); + + rtc.set_datetime(now.into()).expect("datetime not set"); + + // In reality the delay would be much longer + Timer::after(Duration::from_millis(20000)).await; + + let then: NaiveDateTime = rtc.now().unwrap().into(); + info!("Got RTC! {:?}", then.timestamp()); + +} From c9b9be5b819911aaf809df9b55be7e7efa3a1fba Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 2 Jul 2023 22:07:20 +0200 Subject: [PATCH 024/148] hal-common: require DerefMut for peripherals, not just Deref. Otherwise you can create multiple drivers on the same singleton like this: ```rust let mut input = Input::new(&pin, Pull::None); let mut output = Output::new(&pin, Level::Low, Speed::Low); input.is_high(); output.set_high(); input.is_high(); output.set_high(); ``` Thanks @pennae for reporting. --- embassy-hal-common/src/peripheral.rs | 2 +- embassy-stm32/src/dac/mod.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-hal-common/src/peripheral.rs b/embassy-hal-common/src/peripheral.rs index c7133bac..38b4c452 100644 --- a/embassy-hal-common/src/peripheral.rs +++ b/embassy-hal-common/src/peripheral.rs @@ -161,7 +161,7 @@ pub trait Peripheral: Sized { } } -impl<'b, T: Deref> Peripheral for T +impl<'b, T: DerefMut> Peripheral for T where T::Target: Peripheral, { diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 1dc13949..31a2d886 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs @@ -264,7 +264,7 @@ impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> { }); let tx_request = self.dma.request(); - let dma_channel = &self.dma; + let dma_channel = &mut self.dma; let tx_options = crate::dma::TransferOptions { circular, @@ -376,7 +376,7 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> { }); let tx_request = self.dma.request(); - let dma_channel = &self.dma; + let dma_channel = &mut self.dma; let tx_options = crate::dma::TransferOptions { circular, From af15b49bfe30d82b7fcb17511d7e1830b2216f03 Mon Sep 17 00:00:00 2001 From: Philipp Scheff Date: Mon, 3 Jul 2023 22:57:33 +0200 Subject: [PATCH 025/148] fmt --- embassy-stm32/src/can/bxcan.rs | 31 +++++++++++++++++-------------- examples/stm32f7/src/bin/can.rs | 16 ++++++++++------ 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index 4afbb568..260f567b 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs @@ -1,9 +1,8 @@ +use core::cell::{RefCell, RefMut}; use core::future::poll_fn; use core::marker::PhantomData; use core::ops::{Deref, DerefMut}; use core::task::Poll; -use core::cell::RefMut; -use core::cell::RefCell; pub use bxcan; use bxcan::{Data, ExtendedId, Frame, Id, StandardId}; @@ -155,7 +154,11 @@ impl<'d, T: Instance> Can<'d, T> { pub fn set_bitrate(&mut self, bitrate: u32) { let bit_timing = Self::calc_bxcan_timings(T::frequency(), bitrate).unwrap(); - self.can.borrow_mut().modify_config().set_bit_timing(bit_timing).leave_disabled(); + self.can + .borrow_mut() + .modify_config() + .set_bit_timing(bit_timing) + .leave_disabled(); } /// Queues the message to be sent but exerts backpressure @@ -432,19 +435,19 @@ impl<'d, T: Instance> Drop for Can<'d, T> { } } -// impl<'d, T: Instance> Deref for Can<'d, T> { -// type Target = bxcan::Can>; +impl<'d, T: Instance> Deref for Can<'d, T> { + type Target = RefCell>>; -// fn deref(&self) -> &Self::Target { -// self.can.borrow() -// } -// } + fn deref(&self) -> &Self::Target { + &self.can + } +} -// impl<'d, T: Instance> DerefMut for Can<'d, T> { -// fn deref_mut(&mut self) -> &mut Self::Target { -// self.can.borrow_mut() -// } -// } +impl<'d, T: Instance> DerefMut for Can<'d, T> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.can + } +} pub(crate) mod sealed { use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs index d821039c..65af9845 100644 --- a/examples/stm32f7/src/bin/can.rs +++ b/examples/stm32f7/src/bin/can.rs @@ -2,15 +2,17 @@ #![no_main] #![feature(type_alias_impl_trait)] -use core::borrow::BorrowMut; -use core::borrow::Borrow; +use core::borrow::{Borrow, BorrowMut}; + use cortex_m_rt::entry; use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::can::bxcan::filter::Mask32; -use embassy_stm32::can::bxcan::{Fifo, Frame, StandardId, Data}; -use embassy_stm32::can::{Can,CanTx,CanRx, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler}; +use embassy_stm32::can::bxcan::{Data, Fifo, Frame, StandardId}; +use embassy_stm32::can::{ + Can, CanRx, CanTx, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler, +}; use embassy_stm32::gpio::{Input, Pull}; use embassy_stm32::peripherals::CAN3; use {defmt_rtt as _, panic_probe as _}; @@ -44,8 +46,10 @@ async fn main(spawner: Spawner) { let rx_pin = Input::new(&mut p.PA15, Pull::Up); core::mem::forget(rx_pin); - let CAN: &'static mut Can<'static,CAN3> = static_cell::make_static!(Can::new(p.CAN3, p.PA8, p.PA15, Irqs)); - CAN.as_mut().modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); + let CAN: &'static mut Can<'static, CAN3> = static_cell::make_static!(Can::new(p.CAN3, p.PA8, p.PA15, Irqs)); + CAN.as_mut() + .modify_filters() + .enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); CAN.as_mut() .modify_config() From a96f30edf45533cb0e41711556106d1583977081 Mon Sep 17 00:00:00 2001 From: Philipp Scheff Date: Mon, 3 Jul 2023 23:48:07 +0200 Subject: [PATCH 026/148] allow deed code can rx & clippy --- embassy-stm32/src/can/bxcan.rs | 1 + examples/stm32f7/src/bin/can.rs | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index 260f567b..fbb4113e 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs @@ -387,6 +387,7 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { } } +#[allow(dead_code)] pub struct CanRx<'c, 'd, T: Instance> { can: &'c RefCell>>, } diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs index 65af9845..2383c23d 100644 --- a/examples/stm32f7/src/bin/can.rs +++ b/examples/stm32f7/src/bin/can.rs @@ -11,7 +11,7 @@ use embassy_stm32::bind_interrupts; use embassy_stm32::can::bxcan::filter::Mask32; use embassy_stm32::can::bxcan::{Data, Fifo, Frame, StandardId}; use embassy_stm32::can::{ - Can, CanRx, CanTx, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler, + Can, CanTx, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler, }; use embassy_stm32::gpio::{Input, Pull}; use embassy_stm32::peripherals::CAN3; @@ -46,21 +46,21 @@ async fn main(spawner: Spawner) { let rx_pin = Input::new(&mut p.PA15, Pull::Up); core::mem::forget(rx_pin); - let CAN: &'static mut Can<'static, CAN3> = static_cell::make_static!(Can::new(p.CAN3, p.PA8, p.PA15, Irqs)); - CAN.as_mut() + let can: &'static mut Can<'static, CAN3> = static_cell::make_static!(Can::new(p.CAN3, p.PA8, p.PA15, Irqs)); + can.as_mut() .modify_filters() .enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); - CAN.as_mut() + can.as_mut() .modify_config() .set_bit_timing(0x001c0001) // http://www.bittiming.can-wiki.info/ .set_loopback(true) .enable(); - let (tx, mut rx) = CAN.split(); + let (tx, mut rx) = can.split(); - let TX: &'static mut CanTx<'static, 'static, CAN3> = static_cell::make_static!(tx); - spawner.spawn(send_can_message(TX)).unwrap(); + let tx: &'static mut CanTx<'static, 'static, CAN3> = static_cell::make_static!(tx); + spawner.spawn(send_can_message(tx)).unwrap(); loop { let frame = rx.read().await.unwrap(); From e3e8d829330b58d7c6964e761d63cb718267f862 Mon Sep 17 00:00:00 2001 From: Philipp Scheff Date: Mon, 3 Jul 2023 23:52:52 +0200 Subject: [PATCH 027/148] remove unused imports from example --- examples/stm32f7/src/bin/can.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/stm32f7/src/bin/can.rs b/examples/stm32f7/src/bin/can.rs index 2383c23d..1b5b377e 100644 --- a/examples/stm32f7/src/bin/can.rs +++ b/examples/stm32f7/src/bin/can.rs @@ -2,14 +2,11 @@ #![no_main] #![feature(type_alias_impl_trait)] -use core::borrow::{Borrow, BorrowMut}; - -use cortex_m_rt::entry; use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::can::bxcan::filter::Mask32; -use embassy_stm32::can::bxcan::{Data, Fifo, Frame, StandardId}; +use embassy_stm32::can::bxcan::{Fifo, Frame, StandardId}; use embassy_stm32::can::{ Can, CanTx, Rx0InterruptHandler, Rx1InterruptHandler, SceInterruptHandler, TxInterruptHandler, }; From 1869fe02ba8b7dfb503206977d8c70698038c3af Mon Sep 17 00:00:00 2001 From: Philipp Scheff Date: Tue, 4 Jul 2023 00:21:08 +0200 Subject: [PATCH 028/148] make stm32f4 example work --- examples/stm32f4/src/bin/can.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/examples/stm32f4/src/bin/can.rs b/examples/stm32f4/src/bin/can.rs index da895505..08bed88d 100644 --- a/examples/stm32f4/src/bin/can.rs +++ b/examples/stm32f4/src/bin/can.rs @@ -2,8 +2,8 @@ #![no_main] #![feature(type_alias_impl_trait)] -use cortex_m_rt::entry; use defmt::*; +use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::can::bxcan::filter::Mask32; use embassy_stm32::can::bxcan::{Fifo, Frame, StandardId}; @@ -19,8 +19,8 @@ bind_interrupts!(struct Irqs { CAN1_TX => TxInterruptHandler; }); -#[entry] -fn main() -> ! { +#[embassy_executor::main] +async fn main(_spawner: Spawner) { info!("Hello World!"); let mut p = embassy_stm32::init(Default::default()); @@ -34,9 +34,12 @@ fn main() -> ! { let mut can = Can::new(p.CAN1, p.PA11, p.PA12, Irqs); - can.modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); + can.as_mut() + .modify_filters() + .enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); - can.modify_config() + can.as_mut() + .modify_config() .set_bit_timing(0x001c0003) // http://www.bittiming.can-wiki.info/ .set_loopback(true) // Receive own frames .set_silent(true) @@ -45,9 +48,8 @@ fn main() -> ! { let mut i: u8 = 0; loop { let tx_frame = Frame::new_data(unwrap!(StandardId::new(i as _)), [i]); - unwrap!(nb::block!(can.transmit(&tx_frame))); - while !can.is_transmitter_idle() {} - let rx_frame = unwrap!(nb::block!(can.receive())); + can.write(&tx_frame).await; + let (_, rx_frame) = can.read().await.unwrap(); info!("loopback frame {=u8}", unwrap!(rx_frame.data())[0]); i += 1; } From 8359d8c020fc44f795e2230b8ba12fe780f1960b Mon Sep 17 00:00:00 2001 From: Philipp Scheff Date: Tue, 4 Jul 2023 00:34:24 +0200 Subject: [PATCH 029/148] make stm32 can test work --- tests/stm32/src/bin/can.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/stm32/src/bin/can.rs b/tests/stm32/src/bin/can.rs index 33d63d54..05adfe89 100644 --- a/tests/stm32/src/bin/can.rs +++ b/tests/stm32/src/bin/can.rs @@ -43,10 +43,13 @@ async fn main(_spawner: Spawner) { info!("Configuring can..."); - can.modify_filters().enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); + can.as_mut() + .modify_filters() + .enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); - can.set_bitrate(1_000_000); - can.modify_config() + can.as_mut().set_bitrate(1_000_000); + can.as_mut() + .modify_config() .set_loopback(true) // Receive own frames .set_silent(true) // .set_bit_timing(0x001c0003) From a088c4bee6e26947fd8e4d32a5604e47de293ba1 Mon Sep 17 00:00:00 2001 From: Philipp Scheff Date: Tue, 4 Jul 2023 00:39:10 +0200 Subject: [PATCH 030/148] fix stm32 can test --- tests/stm32/src/bin/can.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/stm32/src/bin/can.rs b/tests/stm32/src/bin/can.rs index 05adfe89..8bdd3c24 100644 --- a/tests/stm32/src/bin/can.rs +++ b/tests/stm32/src/bin/can.rs @@ -47,7 +47,7 @@ async fn main(_spawner: Spawner) { .modify_filters() .enable_bank(0, Fifo::Fifo0, Mask32::accept_all()); - can.as_mut().set_bitrate(1_000_000); + can.set_bitrate(1_000_000); can.as_mut() .modify_config() .set_loopback(true) // Receive own frames From d9824dfd646051c1996bf15ef23304864ab9da6e Mon Sep 17 00:00:00 2001 From: William Yager Date: Mon, 3 Jul 2023 19:39:51 -0400 Subject: [PATCH 031/148] Add bank 1 16 bit --- embassy-stm32/src/fmc.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index a4f3b968..26d1640b 100644 --- a/embassy-stm32/src/fmc.rs +++ b/embassy-stm32/src/fmc.rs @@ -86,6 +86,25 @@ macro_rules! fmc_sdram_constructor { } impl<'d, T: Instance> Fmc<'d, T> { + fmc_sdram_constructor!(sdram_a12bits_d16bits_4banks_bank1: ( + bank: stm32_fmc::SdramTargetBank::Bank1, + addr: [ + (a0: A0Pin), (a1: A1Pin), (a2: A2Pin), (a3: A3Pin), (a4: A4Pin), (a5: A5Pin), (a6: A6Pin), (a7: A7Pin), (a8: A8Pin), (a9: A9Pin), (a10: A10Pin), (a11: A11Pin) + ], + ba: [(ba0: BA0Pin), (ba1: BA1Pin)], + d: [ + (d0: D0Pin), (d1: D1Pin), (d2: D2Pin), (d3: D3Pin), (d4: D4Pin), (d5: D5Pin), (d6: D6Pin), (d7: D7Pin), + (d8: D8Pin), (d9: D9Pin), (d10: D10Pin), (d11: D11Pin), (d12: D12Pin), (d13: D13Pin), (d14: D14Pin), (d15: D15Pin) + ], + nbl: [ + (nbl0: NBL0Pin), (nbl1: NBL1Pin) + ], + ctrl: [ + (sdcke: SDCKE0Pin), (sdclk: SDCLKPin), (sdncas: SDNCASPin), (sdne: SDNE0Pin), (sdnras: SDNRASPin), (sdnwe: SDNWEPin) + ] + )); + + fmc_sdram_constructor!(sdram_a12bits_d32bits_4banks_bank1: ( bank: stm32_fmc::SdramTargetBank::Bank1, addr: [ From 0c4180cdd0308a7a5da2a564e1af3c275ecfd105 Mon Sep 17 00:00:00 2001 From: William Yager Date: Mon, 3 Jul 2023 19:39:58 -0400 Subject: [PATCH 032/148] fmt --- embassy-stm32/src/fmc.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index 26d1640b..60d7a00e 100644 --- a/embassy-stm32/src/fmc.rs +++ b/embassy-stm32/src/fmc.rs @@ -104,7 +104,6 @@ impl<'d, T: Instance> Fmc<'d, T> { ] )); - fmc_sdram_constructor!(sdram_a12bits_d32bits_4banks_bank1: ( bank: stm32_fmc::SdramTargetBank::Bank1, addr: [ From 582c721aec06702dcdb808b0b5e1d08ab8dd1353 Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Tue, 4 Jul 2023 11:48:59 +0200 Subject: [PATCH 033/148] Add lifetimes to the functions --- embassy-nrf/src/spim.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 66bbd1a8..16694793 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs @@ -521,11 +521,11 @@ mod eha { } impl<'d, T: Instance> embedded_hal_async::spi::SpiBus for Spim<'d, T> { - async fn transfer(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(), Error> { + async fn transfer<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Result<(), Error> { self.transfer(rx, tx).await } - async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> { + async fn transfer_in_place<'a>(&'a mut self, words: &'a mut [u8]) -> Result<(), Error> { self.transfer_in_place(words).await } } From 40d25da793bd18528f3555d0a9205986018d01f0 Mon Sep 17 00:00:00 2001 From: cumthugo Date: Tue, 4 Jul 2023 21:13:31 +0800 Subject: [PATCH 034/148] time: fix queue size --- embassy-time/src/queue_generic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-time/src/queue_generic.rs b/embassy-time/src/queue_generic.rs index 4795eb2f..77947ab2 100644 --- a/embassy-time/src/queue_generic.rs +++ b/embassy-time/src/queue_generic.rs @@ -16,7 +16,7 @@ const QUEUE_SIZE: usize = 16; #[cfg(feature = "generic-queue-32")] const QUEUE_SIZE: usize = 32; #[cfg(feature = "generic-queue-64")] -const QUEUE_SIZE: usize = 32; +const QUEUE_SIZE: usize = 64; #[cfg(feature = "generic-queue-128")] const QUEUE_SIZE: usize = 128; #[cfg(not(any( From a101d9078deb3ad576a40b6d5f4d6e81dcfd528e Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 4 Jul 2023 19:53:06 +0200 Subject: [PATCH 035/148] update embedded-hal crates. --- cyw43/Cargo.toml | 2 +- embassy-embedded-hal/Cargo.toml | 7 +- .../src/adapter/blocking_async.rs | 49 +++---- .../src/adapter/yielding_async.rs | 47 +++---- .../src/shared_bus/asynch/spi.rs | 126 ++---------------- .../src/shared_bus/blocking/spi.rs | 120 +++-------------- embassy-embedded-hal/src/shared_bus/mod.rs | 4 + embassy-lora/Cargo.toml | 7 +- embassy-net-esp-hosted/Cargo.toml | 4 +- embassy-net-w5500/Cargo.toml | 4 +- embassy-net-w5500/src/spi.rs | 8 +- embassy-nrf/Cargo.toml | 4 +- embassy-nrf/src/spim.rs | 20 +-- embassy-rp/Cargo.toml | 6 +- embassy-rp/src/spi.rs | 20 +-- embassy-stm32/Cargo.toml | 6 +- embassy-stm32/src/spi/mod.rs | 23 +--- embassy-time/Cargo.toml | 4 +- examples/nrf52840/Cargo.toml | 5 +- examples/nrf52840/src/bin/wifi_esp_hosted.rs | 5 +- examples/rp/Cargo.toml | 7 +- .../rp/src/bin/ethernet_w5500_multisocket.rs | 14 +- .../rp/src/bin/ethernet_w5500_tcp_client.rs | 14 +- .../rp/src/bin/ethernet_w5500_tcp_server.rs | 14 +- examples/rp/src/bin/ethernet_w5500_udp.rs | 13 +- examples/rp/src/bin/spi_display.rs | 8 +- examples/stm32h5/Cargo.toml | 4 +- examples/stm32h7/Cargo.toml | 4 +- examples/stm32l0/Cargo.toml | 3 + examples/stm32l4/Cargo.toml | 4 +- examples/stm32wl/Cargo.toml | 3 + tests/nrf/Cargo.toml | 4 +- tests/nrf/src/bin/wifi_esp_hosted_perf.rs | 6 +- tests/rp/Cargo.toml | 4 +- tests/stm32/Cargo.toml | 4 +- 35 files changed, 184 insertions(+), 393 deletions(-) diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index 61caa027..7d2f9dfd 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -24,7 +24,7 @@ cortex-m = "0.7.6" cortex-m-rt = "0.7.0" futures = { version = "0.3.17", default-features = false, features = ["async-await", "cfg-target-has-atomic", "unstable"] } -embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.10" } +embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.11" } num_enum = { version = "0.5.7", default-features = false } [package.metadata.embassy_docs] diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index 35c70bb6..2d11dc3c 100644 --- a/embassy-embedded-hal/Cargo.toml +++ b/embassy-embedded-hal/Cargo.toml @@ -15,15 +15,18 @@ target = "x86_64-unknown-linux-gnu" std = [] # Enable nightly-only features nightly = ["embassy-futures", "embedded-hal-async", "embedded-storage-async"] +time = ["dep:embassy-time"] +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.0", path = "../embassy-time", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [ "unproven", ] } -embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } -embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true } +embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } +embedded-hal-async = { version = "=0.2.0-alpha.2", optional = true } embedded-storage = "0.3.0" embedded-storage-async = { version = "0.4.0", optional = true } nb = "1.0.0" diff --git a/embassy-embedded-hal/src/adapter/blocking_async.rs b/embassy-embedded-hal/src/adapter/blocking_async.rs index b996d6a7..98ae2b02 100644 --- a/embassy-embedded-hal/src/adapter/blocking_async.rs +++ b/embassy-embedded-hal/src/adapter/blocking_async.rs @@ -74,7 +74,21 @@ where E: embedded_hal_1::spi::Error + 'static, T: blocking::spi::Transfer + blocking::spi::Write, { - async fn transfer<'a>(&'a mut self, read: &'a mut [u8], write: &'a [u8]) -> Result<(), Self::Error> { + async fn flush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + + async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> { + self.wrapped.write(data)?; + Ok(()) + } + + async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { + self.wrapped.transfer(data)?; + Ok(()) + } + + async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { // Ensure we write the expected bytes for i in 0..core::cmp::min(read.len(), write.len()) { read[i] = write[i].clone(); @@ -83,38 +97,7 @@ where Ok(()) } - async fn transfer_in_place<'a>(&'a mut self, _: &'a mut [u8]) -> Result<(), Self::Error> { - todo!() - } -} - -impl embedded_hal_async::spi::SpiBusFlush for BlockingAsync -where - E: embedded_hal_1::spi::Error + 'static, - T: blocking::spi::Transfer + blocking::spi::Write, -{ - async fn flush(&mut self) -> Result<(), Self::Error> { - Ok(()) - } -} - -impl embedded_hal_async::spi::SpiBusWrite for BlockingAsync -where - E: embedded_hal_1::spi::Error + 'static, - T: blocking::spi::Transfer + blocking::spi::Write, -{ - async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> { - self.wrapped.write(data)?; - Ok(()) - } -} - -impl embedded_hal_async::spi::SpiBusRead for BlockingAsync -where - E: embedded_hal_1::spi::Error + 'static, - T: blocking::spi::Transfer + blocking::spi::Write, -{ - async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { + async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { self.wrapped.transfer(data)?; Ok(()) } diff --git a/embassy-embedded-hal/src/adapter/yielding_async.rs b/embassy-embedded-hal/src/adapter/yielding_async.rs index f51e4076..fe9c9c34 100644 --- a/embassy-embedded-hal/src/adapter/yielding_async.rs +++ b/embassy-embedded-hal/src/adapter/yielding_async.rs @@ -69,54 +69,39 @@ where type Error = T::Error; } -impl embedded_hal_async::spi::SpiBus for YieldingAsync +impl embedded_hal_async::spi::SpiBus for YieldingAsync where - T: embedded_hal_async::spi::SpiBus, -{ - async fn transfer<'a>(&'a mut self, read: &'a mut [u8], write: &'a [u8]) -> Result<(), Self::Error> { - self.wrapped.transfer(read, write).await?; - yield_now().await; - Ok(()) - } - - async fn transfer_in_place<'a>(&'a mut self, words: &'a mut [u8]) -> Result<(), Self::Error> { - self.wrapped.transfer_in_place(words).await?; - yield_now().await; - Ok(()) - } -} - -impl embedded_hal_async::spi::SpiBusFlush for YieldingAsync -where - T: embedded_hal_async::spi::SpiBusFlush, + T: embedded_hal_async::spi::SpiBus, { async fn flush(&mut self) -> Result<(), Self::Error> { self.wrapped.flush().await?; yield_now().await; Ok(()) } -} -impl embedded_hal_async::spi::SpiBusWrite for YieldingAsync -where - T: embedded_hal_async::spi::SpiBusWrite, -{ - async fn write(&mut self, data: &[u8]) -> Result<(), Self::Error> { + async fn write(&mut self, data: &[Word]) -> Result<(), Self::Error> { self.wrapped.write(data).await?; yield_now().await; Ok(()) } -} -impl embedded_hal_async::spi::SpiBusRead for YieldingAsync -where - T: embedded_hal_async::spi::SpiBusRead, -{ - async fn read(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { + async fn read(&mut self, data: &mut [Word]) -> Result<(), Self::Error> { self.wrapped.read(data).await?; yield_now().await; Ok(()) } + + async fn transfer(&mut self, read: &mut [Word], write: &[Word]) -> Result<(), Self::Error> { + self.wrapped.transfer(read, write).await?; + yield_now().await; + Ok(()) + } + + async fn transfer_in_place(&mut self, words: &mut [Word]) -> Result<(), Self::Error> { + self.wrapped.transfer_in_place(words).await?; + yield_now().await; + Ok(()) + } } /// diff --git a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs index b5549a6c..03039218 100644 --- a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs +++ b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs @@ -56,62 +56,6 @@ where type Error = SpiDeviceError; } -impl spi::SpiDeviceRead for SpiDevice<'_, M, BUS, CS> -where - M: RawMutex, - BUS: spi::SpiBusRead, - CS: OutputPin, -{ - async fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> { - let mut bus = self.bus.lock().await; - self.cs.set_low().map_err(SpiDeviceError::Cs)?; - - let op_res: Result<(), BUS::Error> = try { - for buf in operations { - bus.read(buf).await?; - } - }; - - // On failure, it's important to still flush and deassert CS. - let flush_res = bus.flush().await; - let cs_res = self.cs.set_high(); - - let op_res = op_res.map_err(SpiDeviceError::Spi)?; - flush_res.map_err(SpiDeviceError::Spi)?; - cs_res.map_err(SpiDeviceError::Cs)?; - - Ok(op_res) - } -} - -impl spi::SpiDeviceWrite for SpiDevice<'_, M, BUS, CS> -where - M: RawMutex, - BUS: spi::SpiBusWrite, - CS: OutputPin, -{ - async fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> { - let mut bus = self.bus.lock().await; - self.cs.set_low().map_err(SpiDeviceError::Cs)?; - - let op_res: Result<(), BUS::Error> = try { - for buf in operations { - bus.write(buf).await?; - } - }; - - // On failure, it's important to still flush and deassert CS. - let flush_res = bus.flush().await; - let cs_res = self.cs.set_high(); - - let op_res = op_res.map_err(SpiDeviceError::Spi)?; - flush_res.map_err(SpiDeviceError::Spi)?; - cs_res.map_err(SpiDeviceError::Cs)?; - - Ok(op_res) - } -} - impl spi::SpiDevice for SpiDevice<'_, M, BUS, CS> where M: RawMutex, @@ -129,6 +73,12 @@ where Operation::Write(buf) => bus.write(buf).await?, Operation::Transfer(read, write) => bus.transfer(read, write).await?, Operation::TransferInPlace(buf) => bus.transfer_in_place(buf).await?, + #[cfg(not(feature = "time"))] + Operation::DelayUs(_) => return Err(SpiDeviceError::DelayUsNotSupported), + #[cfg(feature = "time")] + Operation::DelayUs(us) => { + embassy_time::Timer::after(embassy_time::Duration::from_micros(*us as _)).await + } } } }; @@ -172,64 +122,6 @@ where type Error = SpiDeviceError; } -impl spi::SpiDeviceWrite for SpiDeviceWithConfig<'_, M, BUS, CS> -where - M: RawMutex, - BUS: spi::SpiBusWrite + SetConfig, - CS: OutputPin, -{ - async fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> { - let mut bus = self.bus.lock().await; - bus.set_config(&self.config); - self.cs.set_low().map_err(SpiDeviceError::Cs)?; - - let op_res: Result<(), BUS::Error> = try { - for buf in operations { - bus.write(buf).await?; - } - }; - - // On failure, it's important to still flush and deassert CS. - let flush_res = bus.flush().await; - let cs_res = self.cs.set_high(); - - let op_res = op_res.map_err(SpiDeviceError::Spi)?; - flush_res.map_err(SpiDeviceError::Spi)?; - cs_res.map_err(SpiDeviceError::Cs)?; - - Ok(op_res) - } -} - -impl spi::SpiDeviceRead for SpiDeviceWithConfig<'_, M, BUS, CS> -where - M: RawMutex, - BUS: spi::SpiBusRead + SetConfig, - CS: OutputPin, -{ - async fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> { - let mut bus = self.bus.lock().await; - bus.set_config(&self.config); - self.cs.set_low().map_err(SpiDeviceError::Cs)?; - - let op_res: Result<(), BUS::Error> = try { - for buf in operations { - bus.read(buf).await?; - } - }; - - // On failure, it's important to still flush and deassert CS. - let flush_res = bus.flush().await; - let cs_res = self.cs.set_high(); - - let op_res = op_res.map_err(SpiDeviceError::Spi)?; - flush_res.map_err(SpiDeviceError::Spi)?; - cs_res.map_err(SpiDeviceError::Cs)?; - - Ok(op_res) - } -} - impl spi::SpiDevice for SpiDeviceWithConfig<'_, M, BUS, CS> where M: RawMutex, @@ -248,6 +140,12 @@ where Operation::Write(buf) => bus.write(buf).await?, Operation::Transfer(read, write) => bus.transfer(read, write).await?, Operation::TransferInPlace(buf) => bus.transfer_in_place(buf).await?, + #[cfg(not(feature = "time"))] + Operation::DelayUs(_) => return Err(SpiDeviceError::DelayUsNotSupported), + #[cfg(feature = "time")] + Operation::DelayUs(us) => { + embassy_time::Timer::after(embassy_time::Duration::from_micros(*us as _)).await + } } } }; diff --git a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs index 22e013be..6d03d626 100644 --- a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs +++ b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs @@ -22,7 +22,7 @@ use core::cell::RefCell; use embassy_sync::blocking_mutex::raw::RawMutex; use embassy_sync::blocking_mutex::Mutex; use embedded_hal_1::digital::OutputPin; -use embedded_hal_1::spi::{self, Operation, SpiBus, SpiBusRead, SpiBusWrite}; +use embedded_hal_1::spi::{self, Operation, SpiBus}; use crate::shared_bus::SpiDeviceError; use crate::SetConfig; @@ -48,58 +48,6 @@ where type Error = SpiDeviceError; } -impl embedded_hal_1::spi::SpiDeviceRead for SpiDevice<'_, M, BUS, CS> -where - M: RawMutex, - BUS: SpiBusRead, - CS: OutputPin, -{ - fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> { - self.bus.lock(|bus| { - let mut bus = bus.borrow_mut(); - self.cs.set_low().map_err(SpiDeviceError::Cs)?; - - let op_res = operations.iter_mut().try_for_each(|buf| bus.read(buf)); - - // On failure, it's important to still flush and deassert CS. - let flush_res = bus.flush(); - let cs_res = self.cs.set_high(); - - let op_res = op_res.map_err(SpiDeviceError::Spi)?; - flush_res.map_err(SpiDeviceError::Spi)?; - cs_res.map_err(SpiDeviceError::Cs)?; - - Ok(op_res) - }) - } -} - -impl embedded_hal_1::spi::SpiDeviceWrite for SpiDevice<'_, M, BUS, CS> -where - M: RawMutex, - BUS: SpiBusWrite, - CS: OutputPin, -{ - fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> { - self.bus.lock(|bus| { - let mut bus = bus.borrow_mut(); - self.cs.set_low().map_err(SpiDeviceError::Cs)?; - - let op_res = operations.iter().try_for_each(|buf| bus.write(buf)); - - // On failure, it's important to still flush and deassert CS. - let flush_res = bus.flush(); - let cs_res = self.cs.set_high(); - - let op_res = op_res.map_err(SpiDeviceError::Spi)?; - flush_res.map_err(SpiDeviceError::Spi)?; - cs_res.map_err(SpiDeviceError::Cs)?; - - Ok(op_res) - }) - } -} - impl embedded_hal_1::spi::SpiDevice for SpiDevice<'_, M, BUS, CS> where M: RawMutex, @@ -116,6 +64,13 @@ where Operation::Write(buf) => bus.write(buf), Operation::Transfer(read, write) => bus.transfer(read, write), Operation::TransferInPlace(buf) => bus.transfer_in_place(buf), + #[cfg(not(feature = "time"))] + Operation::DelayUs(_) => Err(SpiDeviceError::DelayUsNotSupported), + #[cfg(feature = "time")] + Operation::DelayUs(us) => { + embassy_time::block_for(embassy_time::Duration::from_micros(*us as _)); + Ok(()) + } }); // On failure, it's important to still flush and deassert CS. @@ -199,58 +154,6 @@ where type Error = SpiDeviceError; } -impl embedded_hal_1::spi::SpiDeviceRead for SpiDeviceWithConfig<'_, M, BUS, CS> -where - M: RawMutex, - BUS: SpiBusRead + SetConfig, - CS: OutputPin, -{ - fn read_transaction(&mut self, operations: &mut [&mut [u8]]) -> Result<(), Self::Error> { - self.bus.lock(|bus| { - let mut bus = bus.borrow_mut(); - bus.set_config(&self.config); - self.cs.set_low().map_err(SpiDeviceError::Cs)?; - - let op_res = operations.iter_mut().try_for_each(|buf| bus.read(buf)); - - // On failure, it's important to still flush and deassert CS. - let flush_res = bus.flush(); - let cs_res = self.cs.set_high(); - - let op_res = op_res.map_err(SpiDeviceError::Spi)?; - flush_res.map_err(SpiDeviceError::Spi)?; - cs_res.map_err(SpiDeviceError::Cs)?; - Ok(op_res) - }) - } -} - -impl embedded_hal_1::spi::SpiDeviceWrite for SpiDeviceWithConfig<'_, M, BUS, CS> -where - M: RawMutex, - BUS: SpiBusWrite + SetConfig, - CS: OutputPin, -{ - fn write_transaction(&mut self, operations: &[&[u8]]) -> Result<(), Self::Error> { - self.bus.lock(|bus| { - let mut bus = bus.borrow_mut(); - bus.set_config(&self.config); - self.cs.set_low().map_err(SpiDeviceError::Cs)?; - - let op_res = operations.iter().try_for_each(|buf| bus.write(buf)); - - // On failure, it's important to still flush and deassert CS. - let flush_res = bus.flush(); - let cs_res = self.cs.set_high(); - - let op_res = op_res.map_err(SpiDeviceError::Spi)?; - flush_res.map_err(SpiDeviceError::Spi)?; - cs_res.map_err(SpiDeviceError::Cs)?; - Ok(op_res) - }) - } -} - impl embedded_hal_1::spi::SpiDevice for SpiDeviceWithConfig<'_, M, BUS, CS> where M: RawMutex, @@ -268,6 +171,13 @@ where Operation::Write(buf) => bus.write(buf), Operation::Transfer(read, write) => bus.transfer(read, write), Operation::TransferInPlace(buf) => bus.transfer_in_place(buf), + #[cfg(not(feature = "time"))] + Operation::DelayUs(_) => Err(SpiDeviceError::DelayUsNotSupported), + #[cfg(feature = "time")] + Operation::DelayUs(us) => { + embassy_time::block_for(embassy_time::Duration::from_micros(*us as _)); + Ok(()) + } }); // On failure, it's important to still flush and deassert CS. diff --git a/embassy-embedded-hal/src/shared_bus/mod.rs b/embassy-embedded-hal/src/shared_bus/mod.rs index 617d921e..79a90bd5 100644 --- a/embassy-embedded-hal/src/shared_bus/mod.rs +++ b/embassy-embedded-hal/src/shared_bus/mod.rs @@ -30,11 +30,14 @@ where /// Error returned by SPI device implementations in this crate. #[derive(Copy, Clone, Eq, PartialEq, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] pub enum SpiDeviceError { /// An operation on the inner SPI bus failed. Spi(BUS), /// Setting the value of the Chip Select (CS) pin failed. Cs(CS), + /// DelayUs operations are not supported when the `time` Cargo feature is not enabled. + DelayUsNotSupported, } impl spi::Error for SpiDeviceError @@ -46,6 +49,7 @@ where match self { Self::Spi(e) => e.kind(), Self::Cs(_) => spi::ErrorKind::Other, + Self::DelayUsNotSupported => spi::ErrorKind::Other, } } } diff --git a/embassy-lora/Cargo.toml b/embassy-lora/Cargo.toml index 05b6fa2d..dc44f96d 100644 --- a/embassy-lora/Cargo.toml +++ b/embassy-lora/Cargo.toml @@ -23,8 +23,8 @@ log = { version = "0.4.14", optional = true } embassy-time = { version = "0.1.0", path = "../embassy-time" } 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-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } -embedded-hal-async = { version = "=0.2.0-alpha.1" } +embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } +embedded-hal-async = { version = "=0.2.0-alpha.2" } embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common", default-features = false } futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] } embedded-hal = { version = "0.2", features = ["unproven"] } @@ -32,3 +32,6 @@ bit_field = { version = "0.10" } lora-phy = { version = "1" } lorawan-device = { version = "0.10.0", default-features = false, features = ["async"] } + +[patch.crates-io] +lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml index a7e18ee0..a52570f5 100644 --- a/embassy-net-esp-hosted/Cargo.toml +++ b/embassy-net-esp-hosted/Cargo.toml @@ -12,8 +12,8 @@ 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"} -embedded-hal = { version = "1.0.0-alpha.10" } -embedded-hal-async = { version = "=0.2.0-alpha.1" } +embedded-hal = { version = "1.0.0-alpha.11" } +embedded-hal-async = { version = "=0.2.0-alpha.2" } noproto = { git="https://github.com/embassy-rs/noproto", default-features = false, features = ["derive"] } #noproto = { version = "0.1", path = "/home/dirbaio/noproto", default-features = false, features = ["derive"] } diff --git a/embassy-net-w5500/Cargo.toml b/embassy-net-w5500/Cargo.toml index 37d15c7a..41d41111 100644 --- a/embassy-net-w5500/Cargo.toml +++ b/embassy-net-w5500/Cargo.toml @@ -8,8 +8,8 @@ license = "MIT OR Apache-2.0" edition = "2021" [dependencies] -embedded-hal = { version = "1.0.0-alpha.10" } -embedded-hal-async = { version = "=0.2.0-alpha.1" } +embedded-hal = { version = "1.0.0-alpha.11" } +embedded-hal-async = { version = "=0.2.0-alpha.2" } 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" } diff --git a/embassy-net-w5500/src/spi.rs b/embassy-net-w5500/src/spi.rs index 6cd52c44..07749d6b 100644 --- a/embassy-net-w5500/src/spi.rs +++ b/embassy-net-w5500/src/spi.rs @@ -22,7 +22,11 @@ impl SpiInterface { let address_phase = address.to_be_bytes(); let control_phase = [(block as u8) << 3 | 0b0000_0100]; let data_phase = data; - let operations = &[&address_phase[..], &control_phase, &data_phase]; - self.0.write_transaction(operations).await + let operations = &mut [ + Operation::Write(&address_phase[..]), + Operation::Write(&control_phase), + Operation::Write(&data_phase), + ]; + self.0.transaction(operations).await } } diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 3e858f85..d33740cc 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -98,8 +98,8 @@ embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional=true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } -embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10", optional = true} -embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true} +embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11", optional = true} +embedded-hal-async = { version = "=0.2.0-alpha.2", optional = true} embedded-io = { version = "0.4.0", features = ["async"], optional = true } defmt = { version = "0.3", optional = true } diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 16694793..b7dc332e 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs @@ -468,25 +468,19 @@ mod eh1 { type Error = Error; } - impl<'d, T: Instance> embedded_hal_1::spi::SpiBusFlush for Spim<'d, T> { + impl<'d, T: Instance> embedded_hal_1::spi::SpiBus for Spim<'d, T> { fn flush(&mut self) -> Result<(), Self::Error> { Ok(()) } - } - impl<'d, T: Instance> embedded_hal_1::spi::SpiBusRead for Spim<'d, T> { fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { self.blocking_transfer(words, &[]) } - } - impl<'d, T: Instance> embedded_hal_1::spi::SpiBusWrite for Spim<'d, T> { fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { self.blocking_write(words) } - } - impl<'d, T: Instance> embedded_hal_1::spi::SpiBus for Spim<'d, T> { fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { self.blocking_transfer(read, write) } @@ -502,30 +496,24 @@ mod eha { use super::*; - impl<'d, T: Instance> embedded_hal_async::spi::SpiBusFlush for Spim<'d, T> { + impl<'d, T: Instance> embedded_hal_async::spi::SpiBus for Spim<'d, T> { async fn flush(&mut self) -> Result<(), Error> { Ok(()) } - } - impl<'d, T: Instance> embedded_hal_async::spi::SpiBusRead for Spim<'d, T> { async fn read(&mut self, words: &mut [u8]) -> Result<(), Error> { self.read(words).await } - } - impl<'d, T: Instance> embedded_hal_async::spi::SpiBusWrite for Spim<'d, T> { async fn write(&mut self, data: &[u8]) -> Result<(), Error> { self.write(data).await } - } - impl<'d, T: Instance> embedded_hal_async::spi::SpiBus for Spim<'d, T> { - async fn transfer<'a>(&'a mut self, rx: &'a mut [u8], tx: &'a [u8]) -> Result<(), Error> { + async fn transfer(&mut self, rx: &mut [u8], tx: &[u8]) -> Result<(), Error> { self.transfer(rx, tx).await } - async fn transfer_in_place<'a>(&'a mut self, words: &'a mut [u8]) -> Result<(), Error> { + async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> { self.transfer_in_place(words).await } } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 66823771..a06831a9 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -79,9 +79,9 @@ fixed = "1.23.1" rp-pac = { version = "6" } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } -embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10", optional = true} -embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true} -embedded-hal-nb = { version = "=1.0.0-alpha.2", optional = true} +embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11", optional = true} +embedded-hal-async = { version = "=0.2.0-alpha.2", optional = true} +embedded-hal-nb = { version = "=1.0.0-alpha.3", optional = true} paste = "1.0" pio-proc = {version= "0.2" } diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index e817d074..af101cf4 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -545,25 +545,19 @@ mod eh1 { type Error = Error; } - impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::SpiBusFlush for Spi<'d, T, M> { + impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::SpiBus for Spi<'d, T, M> { fn flush(&mut self) -> Result<(), Self::Error> { Ok(()) } - } - impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::SpiBusRead for Spi<'d, T, M> { fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { self.blocking_transfer(words, &[]) } - } - impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::SpiBusWrite for Spi<'d, T, M> { fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { self.blocking_write(words) } - } - impl<'d, T: Instance, M: Mode> embedded_hal_1::spi::SpiBus for Spi<'d, T, M> { fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { self.blocking_transfer(read, write) } @@ -578,30 +572,24 @@ mod eh1 { mod eha { use super::*; - impl<'d, T: Instance> embedded_hal_async::spi::SpiBusFlush for Spi<'d, T, Async> { + impl<'d, T: Instance> embedded_hal_async::spi::SpiBus for Spi<'d, T, Async> { async fn flush(&mut self) -> Result<(), Self::Error> { Ok(()) } - } - impl<'d, T: Instance> embedded_hal_async::spi::SpiBusWrite for Spi<'d, T, Async> { async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { self.write(words).await } - } - impl<'d, T: Instance> embedded_hal_async::spi::SpiBusRead for Spi<'d, T, Async> { async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { self.read(words).await } - } - impl<'d, T: Instance> embedded_hal_async::spi::SpiBus for Spi<'d, T, Async> { - async fn transfer<'a>(&'a mut self, read: &'a mut [u8], write: &'a [u8]) -> Result<(), Self::Error> { + async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { self.transfer(read, write).await } - async fn transfer_in_place<'a>(&'a mut self, words: &'a mut [u8]) -> Result<(), Self::Error> { + async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { self.transfer_in_place(words).await } } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index b3fe9c1f..04514963 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -40,9 +40,9 @@ embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } -embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10", optional = true} -embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true} -embedded-hal-nb = { version = "=1.0.0-alpha.2", optional = true} +embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11", optional = true} +embedded-hal-async = { version = "=0.2.0-alpha.2", optional = true} +embedded-hal-nb = { version = "=1.0.0-alpha.3", optional = true} embedded-storage = "0.3.0" embedded-storage-async = { version = "0.4.0", optional = true } diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index c3224073..d5f63f84 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -852,25 +852,19 @@ mod eh1 { type Error = Error; } - impl<'d, T: Instance, Tx, Rx> embedded_hal_1::spi::SpiBusFlush for Spi<'d, T, Tx, Rx> { + impl<'d, T: Instance, W: Word, Tx, Rx> embedded_hal_1::spi::SpiBus for Spi<'d, T, Tx, Rx> { fn flush(&mut self) -> Result<(), Self::Error> { Ok(()) } - } - impl<'d, T: Instance, W: Word, Tx, Rx> embedded_hal_1::spi::SpiBusRead for Spi<'d, T, Tx, Rx> { fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error> { self.blocking_read(words) } - } - impl<'d, T: Instance, W: Word, Tx, Rx> embedded_hal_1::spi::SpiBusWrite for Spi<'d, T, Tx, Rx> { fn write(&mut self, words: &[W]) -> Result<(), Self::Error> { self.blocking_write(words) } - } - impl<'d, T: Instance, W: Word, Tx, Rx> embedded_hal_1::spi::SpiBus for Spi<'d, T, Tx, Rx> { fn transfer(&mut self, read: &mut [W], write: &[W]) -> Result<(), Self::Error> { self.blocking_transfer(read, write) } @@ -895,32 +889,25 @@ mod eh1 { #[cfg(all(feature = "unstable-traits", feature = "nightly"))] mod eha { use super::*; - impl<'d, T: Instance, Tx, Rx> embedded_hal_async::spi::SpiBusFlush for Spi<'d, T, Tx, Rx> { + + impl<'d, T: Instance, Tx: TxDma, Rx: RxDma, W: Word> embedded_hal_async::spi::SpiBus for Spi<'d, T, Tx, Rx> { async fn flush(&mut self) -> Result<(), Self::Error> { Ok(()) } - } - impl<'d, T: Instance, Tx: TxDma, Rx, W: Word> embedded_hal_async::spi::SpiBusWrite for Spi<'d, T, Tx, Rx> { async fn write(&mut self, words: &[W]) -> Result<(), Self::Error> { self.write(words).await } - } - impl<'d, T: Instance, Tx: TxDma, Rx: RxDma, W: Word> embedded_hal_async::spi::SpiBusRead - for Spi<'d, T, Tx, Rx> - { async fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error> { self.read(words).await } - } - impl<'d, T: Instance, Tx: TxDma, Rx: RxDma, W: Word> embedded_hal_async::spi::SpiBus for Spi<'d, T, Tx, Rx> { - async fn transfer<'a>(&'a mut self, read: &'a mut [W], write: &'a [W]) -> Result<(), Self::Error> { + async fn transfer(&mut self, read: &mut [W], write: &[W]) -> Result<(), Self::Error> { self.transfer(read, write).await } - async fn transfer_in_place<'a>(&'a mut self, words: &'a mut [W]) -> Result<(), Self::Error> { + async fn transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Self::Error> { self.transfer_in_place(words).await } } diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index 857da546..0213eef0 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -152,8 +152,8 @@ defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6" } -embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10", optional = true} -embedded-hal-async = { version = "=0.2.0-alpha.1", optional = true} +embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11", optional = true} +embedded-hal-async = { version = "=0.2.0-alpha.2", optional = true} futures-util = { version = "0.3.17", default-features = false } atomic-polyfill = "1.0.1" diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 8c417596..2ccd5045 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -52,4 +52,7 @@ rand = { version = "0.8.4", default-features = false } embedded-storage = "0.3.0" usbd-hid = "0.6.0" serde = { version = "1.0.136", default-features = false } -embedded-hal-async = { version = "0.2.0-alpha.1", optional = true } +embedded-hal-async = { version = "0.2.0-alpha.2", optional = true } + +[patch.crates-io] +lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } diff --git a/examples/nrf52840/src/bin/wifi_esp_hosted.rs b/examples/nrf52840/src/bin/wifi_esp_hosted.rs index 4eb31b10..f7496703 100644 --- a/examples/nrf52840/src/bin/wifi_esp_hosted.rs +++ b/examples/nrf52840/src/bin/wifi_esp_hosted.rs @@ -10,6 +10,7 @@ use embassy_nrf::gpio::{AnyPin, Input, Level, Output, OutputDrive, Pin, Pull}; use embassy_nrf::rng::Rng; use embassy_nrf::spim::{self, Spim}; use embassy_nrf::{bind_interrupts, peripherals}; +use embassy_time::Delay; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use static_cell::make_static; @@ -24,7 +25,7 @@ bind_interrupts!(struct Irqs { async fn wifi_task( runner: hosted::Runner< 'static, - ExclusiveDevice, Output<'static, peripherals::P0_31>>, + ExclusiveDevice, Output<'static, peripherals::P0_31>, Delay>, Input<'static, AnyPin>, Output<'static, peripherals::P1_05>, >, @@ -55,7 +56,7 @@ async fn main(spawner: Spawner) { config.frequency = spim::Frequency::M32; config.mode = spim::MODE_2; // !!! let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); - let spi = ExclusiveDevice::new(spi, cs); + let spi = ExclusiveDevice::new(spi, cs, Delay); let (device, mut control, runner) = embassy_net_esp_hosted::new( make_static!(embassy_net_esp_hosted::State::new()), diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 48f3a26b..17ebea86 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -41,8 +41,8 @@ byte-slice-cast = { version = "1.2.0", default-features = false } smart-leds = "0.3.0" heapless = "0.7.15" -embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } -embedded-hal-async = "0.2.0-alpha.1" +embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } +embedded-hal-async = "0.2.0-alpha.2" embedded-io = { version = "0.4.0", features = ["async", "defmt"] } embedded-storage = { version = "0.3" } static_cell = { version = "1.1", features = ["nightly"]} @@ -53,3 +53,6 @@ rand = { version = "0.8.5", default-features = false } [profile.release] debug = true + +[patch.crates-io] +lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs index 82568254..e81da177 100644 --- a/examples/rp/src/bin/ethernet_w5500_multisocket.rs +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -15,7 +15,7 @@ use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Input, Level, Output, Pull}; use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; -use embassy_time::Duration; +use embassy_time::{Delay, Duration}; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; @@ -26,7 +26,7 @@ use {defmt_rtt as _, panic_probe as _}; async fn ethernet_task( runner: Runner< 'static, - ExclusiveDevice, Output<'static, PIN_17>>, + ExclusiveDevice, Output<'static, PIN_17>, Delay>, Input<'static, PIN_21>, Output<'static, PIN_20>, >, @@ -54,8 +54,14 @@ async fn main(spawner: Spawner) { let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; let state = make_static!(State::<8, 8>::new()); - let (device, runner) = - embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await; unwrap!(spawner.spawn(ethernet_task(runner))); // Generate random seed diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs index d562defa..9dd7ae97 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -17,7 +17,7 @@ use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Input, Level, Output, Pull}; use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; -use embassy_time::{Duration, Timer}; +use embassy_time::{Delay, Duration, Timer}; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; @@ -28,7 +28,7 @@ use {defmt_rtt as _, panic_probe as _}; async fn ethernet_task( runner: Runner< 'static, - ExclusiveDevice, Output<'static, PIN_17>>, + ExclusiveDevice, Output<'static, PIN_17>, Delay>, Input<'static, PIN_21>, Output<'static, PIN_20>, >, @@ -57,8 +57,14 @@ async fn main(spawner: Spawner) { let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; let state = make_static!(State::<8, 8>::new()); - let (device, runner) = - embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await; unwrap!(spawner.spawn(ethernet_task(runner))); // Generate random seed diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs index 7f521cdb..db21c2b6 100644 --- a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -16,7 +16,7 @@ use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Input, Level, Output, Pull}; use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; -use embassy_time::Duration; +use embassy_time::{Delay, Duration}; use embedded_hal_async::spi::ExclusiveDevice; use embedded_io::asynch::Write; use rand::RngCore; @@ -26,7 +26,7 @@ use {defmt_rtt as _, panic_probe as _}; async fn ethernet_task( runner: Runner< 'static, - ExclusiveDevice, Output<'static, PIN_17>>, + ExclusiveDevice, Output<'static, PIN_17>, Delay>, Input<'static, PIN_21>, Output<'static, PIN_20>, >, @@ -55,8 +55,14 @@ async fn main(spawner: Spawner) { let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; let state = make_static!(State::<8, 8>::new()); - let (device, runner) = - embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await; unwrap!(spawner.spawn(ethernet_task(runner))); // Generate random seed diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs index ada86ae5..038432b1 100644 --- a/examples/rp/src/bin/ethernet_w5500_udp.rs +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -16,6 +16,7 @@ use embassy_rp::clocks::RoscRng; use embassy_rp::gpio::{Input, Level, Output, Pull}; use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::Delay; use embedded_hal_async::spi::ExclusiveDevice; use rand::RngCore; use static_cell::make_static; @@ -24,7 +25,7 @@ use {defmt_rtt as _, panic_probe as _}; async fn ethernet_task( runner: Runner< 'static, - ExclusiveDevice, Output<'static, PIN_17>>, + ExclusiveDevice, Output<'static, PIN_17>, Delay>, Input<'static, PIN_21>, Output<'static, PIN_20>, >, @@ -52,8 +53,14 @@ async fn main(spawner: Spawner) { let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; let state = make_static!(State::<8, 8>::new()); - let (device, runner) = - embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await; + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs, Delay), + w5500_int, + w5500_reset, + ) + .await; unwrap!(spawner.spawn(ethernet_task(runner))); // Generate random seed diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs index 85a19ce0..2fd20159 100644 --- a/examples/rp/src/bin/spi_display.rs +++ b/examples/rp/src/bin/spi_display.rs @@ -175,7 +175,7 @@ mod touch { mod my_display_interface { use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand}; use embedded_hal_1::digital::OutputPin; - use embedded_hal_1::spi::SpiDeviceWrite; + use embedded_hal_1::spi::SpiDevice; /// SPI display interface. /// @@ -187,7 +187,7 @@ mod my_display_interface { impl SPIDeviceInterface where - SPI: SpiDeviceWrite, + SPI: SpiDevice, DC: OutputPin, { /// Create new SPI interface for communciation with a display driver @@ -198,7 +198,7 @@ mod my_display_interface { impl WriteOnlyDataCommand for SPIDeviceInterface where - SPI: SpiDeviceWrite, + SPI: SpiDevice, DC: OutputPin, { fn send_commands(&mut self, cmds: DataFormat<'_>) -> Result<(), DisplayError> { @@ -218,7 +218,7 @@ mod my_display_interface { } } - fn send_u8(spi: &mut T, words: DataFormat<'_>) -> Result<(), T::Error> { + fn send_u8(spi: &mut T, words: DataFormat<'_>) -> Result<(), T::Error> { match words { DataFormat::U8(slice) => spi.write(slice), DataFormat::U16(slice) => { diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index ebe51134..789ef59c 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -19,8 +19,8 @@ defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } -embedded-hal-async = { version = "=0.2.0-alpha.1" } +embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } +embedded-hal-async = { version = "=0.2.0-alpha.2" } embedded-nal-async = "0.4.0" panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 62ef5e9e..04a2baab 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -19,8 +19,8 @@ defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } -embedded-hal-async = { version = "=0.2.0-alpha.1" } +embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } +embedded-hal-async = { version = "=0.2.0-alpha.2" } embedded-nal-async = "0.4.0" panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 2ead714e..988fd3a7 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -32,3 +32,6 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa heapless = { version = "0.7.5", default-features = false } embedded-hal = "0.2.6" static_cell = "1.1" + +[patch.crates-io] +lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 3bb473ef..7d066bb8 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -18,8 +18,8 @@ defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } -embedded-hal-async = { version = "=0.2.0-alpha.1" } +embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } +embedded-hal-async = { version = "=0.2.0-alpha.2" } 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 } diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 260f9afa..75a5f1c4 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -25,3 +25,6 @@ embedded-storage = "0.3.0" 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 } + +[patch.crates-io] +lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml index 4f9ecc47..247287e4 100644 --- a/tests/nrf/Cargo.toml +++ b/tests/nrf/Cargo.toml @@ -10,12 +10,12 @@ 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-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "nightly", "defmt-timestamp-uptime"] } +embassy-time = { version = "0.1.0", 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 = { version = "0.4.0", features = ["async"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] } embassy-net-esp-hosted = { version = "0.1.0", path = "../../embassy-net-esp-hosted", features = ["defmt"] } -embedded-hal-async = { version = "0.2.0-alpha.1" } +embedded-hal-async = { version = "0.2.0-alpha.2" } static_cell = { version = "1.1", features = [ "nightly" ] } defmt = "0.3" diff --git a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs index 277b985c..398ab9d2 100644 --- a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs +++ b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs @@ -14,7 +14,7 @@ use embassy_nrf::gpio::{AnyPin, Input, Level, Output, OutputDrive, Pin, Pull}; use embassy_nrf::rng::Rng; use embassy_nrf::spim::{self, Spim}; use embassy_nrf::{bind_interrupts, peripherals}; -use embassy_time::{with_timeout, Duration, Timer}; +use embassy_time::{with_timeout, Delay, Duration, Timer}; use embedded_hal_async::spi::ExclusiveDevice; use static_cell::make_static; use {defmt_rtt as _, embassy_net_esp_hosted as hosted, panic_probe as _}; @@ -30,7 +30,7 @@ bind_interrupts!(struct Irqs { async fn wifi_task( runner: hosted::Runner< 'static, - ExclusiveDevice, Output<'static, peripherals::P0_31>>, + ExclusiveDevice, Output<'static, peripherals::P0_31>, Delay>, Input<'static, AnyPin>, Output<'static, peripherals::P1_05>, >, @@ -63,7 +63,7 @@ async fn main(spawner: Spawner) { config.frequency = spim::Frequency::M32; config.mode = spim::MODE_2; // !!! let spi = spim::Spim::new(p.SPI3, Irqs, sck, miso, mosi, config); - let spi = ExclusiveDevice::new(spi, cs); + let spi = ExclusiveDevice::new(spi, cs, Delay); let (device, mut control, runner) = embassy_net_esp_hosted::new( make_static!(embassy_net_esp_hosted::State::new()), diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 180d0ebb..f1b48e74 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -22,8 +22,8 @@ defmt-rtt = "0.4" cortex-m = { version = "0.7.6" } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } -embedded-hal-async = { version = "=0.2.0-alpha.1" } +embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } +embedded-hal-async = { version = "=0.2.0-alpha.2" } panic-probe = { version = "0.3.0", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } embedded-io = { version = "0.4.0", features = ["async"] } diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index c2422f7b..c69af6d5 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -38,8 +38,8 @@ defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10" } -embedded-hal-async = { version = "=0.2.0-alpha.1" } +embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } +embedded-hal-async = { version = "=0.2.0-alpha.2" } 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 } From 10c0174903e6414d8d88b2636c65604ea85f4a8e Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 4 Jul 2023 20:10:45 +0200 Subject: [PATCH 036/148] doc: upload statics too. --- .github/ci/doc.sh | 49 ++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 1402e742..e4d83e4b 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -15,30 +15,31 @@ export BUILDER_COMPRESS=true # which makes rustup very sad rustc --version > /dev/null -docserver-builder -i ./embassy-stm32 -o crates/embassy-stm32/git.zup -docserver-builder -i ./embassy-boot/boot -o crates/embassy-boot/git.zup -docserver-builder -i ./embassy-boot/nrf -o crates/embassy-boot-nrf/git.zup -docserver-builder -i ./embassy-boot/rp -o crates/embassy-boot-rp/git.zup -docserver-builder -i ./embassy-boot/stm32 -o crates/embassy-boot-stm32/git.zup -docserver-builder -i ./embassy-embedded-hal -o crates/embassy-embedded-hal/git.zup -docserver-builder -i ./embassy-executor -o crates/embassy-executor/git.zup -docserver-builder -i ./embassy-futures -o crates/embassy-futures/git.zup -docserver-builder -i ./embassy-lora -o crates/embassy-lora/git.zup -docserver-builder -i ./embassy-net -o crates/embassy-net/git.zup -docserver-builder -i ./embassy-net-driver -o crates/embassy-net-driver/git.zup -docserver-builder -i ./embassy-net-driver-channel -o crates/embassy-net-driver-channel/git.zup -docserver-builder -i ./embassy-nrf -o crates/embassy-nrf/git.zup -docserver-builder -i ./embassy-rp -o crates/embassy-rp/git.zup -docserver-builder -i ./embassy-sync -o crates/embassy-sync/git.zup -docserver-builder -i ./embassy-time -o crates/embassy-time/git.zup -docserver-builder -i ./embassy-usb -o crates/embassy-usb/git.zup -docserver-builder -i ./embassy-usb-driver -o crates/embassy-usb-driver/git.zup -docserver-builder -i ./embassy-usb-logger -o crates/embassy-usb-logger/git.zup -docserver-builder -i ./cyw43 -o crates/cyw43/git.zup -docserver-builder -i ./cyw43-pio -o crates/cyw43-pio/git.zup -docserver-builder -i ./embassy-net-w5500 -o crates/embassy-net-w5500/git.zup -docserver-builder -i ./embassy-stm32-wpan -o crates/embassy-stm32-wpan/git.zup +docserver-builder -i ./embassy-stm32 -o webroot/crates/embassy-stm32/git.zup +docserver-builder -i ./embassy-boot/boot -o webroot/crates/embassy-boot/git.zup +docserver-builder -i ./embassy-boot/nrf -o webroot/crates/embassy-boot-nrf/git.zup +docserver-builder -i ./embassy-boot/rp -o webroot/crates/embassy-boot-rp/git.zup +docserver-builder -i ./embassy-boot/stm32 -o webroot/crates/embassy-boot-stm32/git.zup +docserver-builder -i ./embassy-embedded-hal -o webroot/crates/embassy-embedded-hal/git.zup +docserver-builder -i ./embassy-executor -o webroot/crates/embassy-executor/git.zup +docserver-builder -i ./embassy-futures -o webroot/crates/embassy-futures/git.zup +docserver-builder -i ./embassy-lora -o webroot/crates/embassy-lora/git.zup +docserver-builder -i ./embassy-net -o webroot/crates/embassy-net/git.zup +docserver-builder -i ./embassy-net-driver -o webroot/crates/embassy-net-driver/git.zup +docserver-builder -i ./embassy-net-driver-channel -o webroot/crates/embassy-net-driver-channel/git.zup +docserver-builder -i ./embassy-nrf -o webroot/crates/embassy-nrf/git.zup +docserver-builder -i ./embassy-rp -o webroot/crates/embassy-rp/git.zup +docserver-builder -i ./embassy-sync -o webroot/crates/embassy-sync/git.zup +docserver-builder -i ./embassy-time -o webroot/crates/embassy-time/git.zup +docserver-builder -i ./embassy-usb -o webroot/crates/embassy-usb/git.zup +docserver-builder -i ./embassy-usb-driver -o webroot/crates/embassy-usb-driver/git.zup +docserver-builder -i ./embassy-usb-logger -o webroot/crates/embassy-usb-logger/git.zup +docserver-builder -i ./cyw43 -o webroot/crates/cyw43/git.zup +docserver-builder -i ./cyw43-pio -o webroot/crates/cyw43-pio/git.zup +docserver-builder -i ./embassy-net-w5500 -o webroot/crates/embassy-net-w5500/git.zup +docserver-builder -i ./embassy-stm32-wpan -o webroot/crates/embassy-stm32-wpan/git.zup --output-static webroot/static export KUBECONFIG=/ci/secrets/kubeconfig.yml POD=$(kubectl -n embassy get po -l app=docserver -o jsonpath={.items[0].metadata.name}) -kubectl cp crates $POD:/data +kubectl cp webroot/crates $POD:/data +kubectl cp webroot/static $POD:/data \ No newline at end of file From 2a035a24a62c3534c09ef26e00a96f6e1f185ff7 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 4 Jul 2023 20:11:00 +0200 Subject: [PATCH 037/148] Update nightly. --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index fd454db2..c201d8bd 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-05-18" +channel = "nightly-2023-07-03" components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] targets = [ "thumbv7em-none-eabi", From 9c4df46c46bb4eb88dff6017bbecf5cf807c8cac Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 4 Jul 2023 21:34:55 +0200 Subject: [PATCH 038/148] rustfmt. --- cyw43/src/runner.rs | 20 +++++++++++++++----- embassy-net-esp-hosted/src/control.rs | 12 +++++++++--- embassy-net-esp-hosted/src/lib.rs | 4 ++-- embassy-stm32/src/rcc/h5.rs | 4 ++-- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/cyw43/src/runner.rs b/cyw43/src/runner.rs index 5706696b..1c187faa 100644 --- a/cyw43/src/runner.rs +++ b/cyw43/src/runner.rs @@ -345,7 +345,9 @@ where } fn rx(&mut self, packet: &mut [u8]) { - let Some((sdpcm_header, payload)) = SdpcmHeader::parse(packet) else { return }; + let Some((sdpcm_header, payload)) = SdpcmHeader::parse(packet) else { + return; + }; self.update_credit(&sdpcm_header); @@ -353,7 +355,9 @@ where match channel { CHANNEL_TYPE_CONTROL => { - let Some((cdc_header, response)) = CdcHeader::parse(payload) else { return; }; + let Some((cdc_header, response)) = CdcHeader::parse(payload) else { + return; + }; trace!(" {:?}", cdc_header); if cdc_header.id == self.ioctl_id { @@ -417,8 +421,12 @@ where let status = event_packet.msg.status; let event_payload = match evt_type { Event::ESCAN_RESULT if status == EStatus::PARTIAL => { - let Some((_, bss_info)) = ScanResults::parse(evt_data) else { return }; - let Some(bss_info) = BssInfo::parse(bss_info) else { return }; + let Some((_, bss_info)) = ScanResults::parse(evt_data) else { + return; + }; + let Some(bss_info) = BssInfo::parse(bss_info) else { + return; + }; events::Payload::BssInfo(*bss_info) } Event::ESCAN_RESULT => events::Payload::None, @@ -439,7 +447,9 @@ where } } CHANNEL_TYPE_DATA => { - let Some((_, packet)) = BdcHeader::parse(payload) else { return }; + let Some((_, packet)) = BdcHeader::parse(payload) else { + return; + }; trace!("rx pkt {:02x}", Bytes(&packet[..packet.len().min(48)])); match self.ch.try_rx_buf() { diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs index fce82ade..79f8cde7 100644 --- a/embassy-net-esp-hosted/src/control.rs +++ b/embassy-net-esp-hosted/src/control.rs @@ -54,7 +54,9 @@ impl<'a> Control<'a> { })), }; let resp = self.ioctl(req).await; - let proto::CtrlMsgPayload::RespConnectAp(resp) = resp.payload.unwrap() else { panic!("unexpected resp") }; + let proto::CtrlMsgPayload::RespConnectAp(resp) = resp.payload.unwrap() else { + panic!("unexpected resp") + }; debug!("======= {:?}", Debug2Format(&resp)); assert_eq!(resp.resp, 0); self.state_ch.set_link_state(LinkState::Up); @@ -71,7 +73,9 @@ impl<'a> Control<'a> { )), }; let resp = self.ioctl(req).await; - let proto::CtrlMsgPayload::RespGetMacAddress(resp) = resp.payload.unwrap() else { panic!("unexpected resp") }; + let proto::CtrlMsgPayload::RespGetMacAddress(resp) = resp.payload.unwrap() else { + panic!("unexpected resp") + }; assert_eq!(resp.resp, 0); // WHY IS THIS A STRING? WHYYYY @@ -100,7 +104,9 @@ impl<'a> Control<'a> { payload: Some(proto::CtrlMsgPayload::ReqSetWifiMode(proto::CtrlMsgReqSetMode { mode })), }; let resp = self.ioctl(req).await; - let proto::CtrlMsgPayload::RespSetWifiMode(resp) = resp.payload.unwrap() else { panic!("unexpected resp") }; + let proto::CtrlMsgPayload::RespSetWifiMode(resp) = resp.payload.unwrap() else { + panic!("unexpected resp") + }; assert_eq!(resp.resp, 0); } diff --git a/embassy-net-esp-hosted/src/lib.rs b/embassy-net-esp-hosted/src/lib.rs index 44dfbe89..a35adfca 100644 --- a/embassy-net-esp-hosted/src/lib.rs +++ b/embassy-net-esp-hosted/src/lib.rs @@ -311,14 +311,14 @@ where fn handle_event(&self, data: &[u8]) { let Ok(event) = noproto::read::(data) else { warn!("failed to parse event"); - return + return; }; debug!("event: {:?}", &event); let Some(payload) = &event.payload else { warn!("event without payload?"); - return + return; }; match payload { diff --git a/embassy-stm32/src/rcc/h5.rs b/embassy-stm32/src/rcc/h5.rs index 4025a4e0..7e2f75ab 100644 --- a/embassy-stm32/src/rcc/h5.rs +++ b/embassy-stm32/src/rcc/h5.rs @@ -473,11 +473,11 @@ fn init_pll(num: usize, config: Option, input: &PllInput) -> PllOutput { w.set_divm(0); }); - return PllOutput{ + return PllOutput { p: None, q: None, r: None, - } + }; }; assert!(1 <= config.prediv && config.prediv <= 63); From 953c745ed86341dba1ce96a15cc03348e1120766 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 4 Jul 2023 16:29:46 -0500 Subject: [PATCH 039/148] stm32/rcc: allow const-propagation --- embassy-stm32/build.rs | 4 +--- embassy-stm32/src/rcc/mod.rs | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index fa66da1f..995ad144 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -348,9 +348,7 @@ fn main() { g.extend(quote! { impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { fn frequency() -> crate::time::Hertz { - critical_section::with(|_| unsafe { - crate::rcc::get_freqs().#clk - }) + unsafe { crate::rcc::get_freqs().#clk } } fn enable() { critical_section::with(|_| { diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index d6816d6a..886fc0b9 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -83,12 +83,12 @@ static mut CLOCK_FREQS: MaybeUninit = MaybeUninit::uninit(); /// Safety: Sets a mutable global. pub(crate) unsafe fn set_freqs(freqs: Clocks) { debug!("rcc: {:?}", freqs); - CLOCK_FREQS.as_mut_ptr().write(freqs); + CLOCK_FREQS = MaybeUninit::new(freqs); } /// Safety: Reads a mutable global. pub(crate) unsafe fn get_freqs() -> &'static Clocks { - &*CLOCK_FREQS.as_ptr() + CLOCK_FREQS.assume_init_ref() } #[cfg(feature = "unstable-pac")] From 70c05c62e49b7b8c2d6d47a7eb567f88b22aa7dc Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 5 Jul 2023 00:35:22 +0200 Subject: [PATCH 040/148] nrf: build docs with `time` feature. --- embassy-nrf/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index d33740cc..ae76af3e 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" src_base = "https://github.com/embassy-rs/embassy/blob/embassy-nrf-v$VERSION/embassy-nrf/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-nrf/src/" -features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "gpiote", "time-driver-rtc1"] +features = ["nightly", "time", "defmt", "unstable-pac", "unstable-traits", "gpiote", "time-driver-rtc1"] flavors = [ { regex_feature = "nrf52.*", target = "thumbv7em-none-eabihf" }, { regex_feature = "nrf53.*", target = "thumbv8m.main-none-eabihf" }, From 2c5146f19fad4344222dee916687b750896a7487 Mon Sep 17 00:00:00 2001 From: Cameron Date: Wed, 5 Jul 2023 09:20:56 +0200 Subject: [PATCH 041/148] Fixed Lifetimes in Events & Tasks --- embassy-nrf/src/ppi/mod.rs | 4 ++-- embassy-nrf/src/ppi/ppi.rs | 4 ++-- embassy-nrf/src/timer.rs | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs index 9092529a..c2bc0f58 100644 --- a/embassy-nrf/src/ppi/mod.rs +++ b/embassy-nrf/src/ppi/mod.rs @@ -96,7 +96,7 @@ impl<'d, G: Group> PpiGroup<'d, G> { /// Get a reference to the "enable all" task. /// /// When triggered, it will enable all the channels in this group. - pub fn task_enable_all(&self) -> Task { + pub fn task_enable_all<'s: 'd>(&'d self) -> Task<'s> { let n = self.g.number(); Task::from_reg(®s().tasks_chg[n].en) } @@ -104,7 +104,7 @@ impl<'d, G: Group> PpiGroup<'d, G> { /// Get a reference to the "disable all" task. /// /// When triggered, it will disable all the channels in this group. - pub fn task_disable_all(&self) -> Task { + pub fn task_disable_all<'s: 'd>(&self) -> Task<'s> { let n = self.g.number(); Task::from_reg(®s().tasks_chg[n].dis) } diff --git a/embassy-nrf/src/ppi/ppi.rs b/embassy-nrf/src/ppi/ppi.rs index 6e8a669d..d0a70b85 100644 --- a/embassy-nrf/src/ppi/ppi.rs +++ b/embassy-nrf/src/ppi/ppi.rs @@ -34,7 +34,7 @@ impl<'d, C: StaticChannel> Ppi<'d, C, 0, 1> { impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { /// Configure PPI channel to trigger `task` on `event`. - pub fn new_one_to_one(ch: impl Peripheral

+ 'd, event: Event, task: Task) -> Self { + pub fn new_one_to_one(ch: impl Peripheral

+ 'd, event: Event<'d>, task: Task<'d>) -> Self { into_ref!(ch); let r = regs(); @@ -49,7 +49,7 @@ impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { #[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { /// Configure PPI channel to trigger both `task1` and `task2` on `event`. - pub fn new_one_to_two(ch: impl Peripheral

+ 'd, event: Event, task1: Task, task2: Task) -> Self { + pub fn new_one_to_two(ch: impl Peripheral

+ 'd, event: Event<'d>, task1: Task<'d>, task2: Task<'d>) -> Self { into_ref!(ch); let r = regs(); diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index dc375785..fed576c3 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs @@ -168,21 +168,21 @@ impl<'d, T: Instance> Timer<'d, T> { /// Returns the START task, for use with PPI. /// /// When triggered, this task starts the timer. - pub fn task_start(&self) -> Task { + pub fn task_start<'s: 'd>(&self) -> Task<'s> { Task::from_reg(&T::regs().tasks_start) } /// Returns the STOP task, for use with PPI. /// /// When triggered, this task stops the timer. - pub fn task_stop(&self) -> Task { + pub fn task_stop<'s: 'd>(&self) -> Task<'s> { Task::from_reg(&T::regs().tasks_stop) } /// Returns the CLEAR task, for use with PPI. /// /// When triggered, this task resets the timer's counter to 0. - pub fn task_clear(&self) -> Task { + pub fn task_clear<'s: 'd>(&self) -> Task<'s> { Task::from_reg(&T::regs().tasks_clear) } @@ -190,7 +190,7 @@ impl<'d, T: Instance> Timer<'d, T> { /// /// When triggered, this task increments the timer's counter by 1. /// Only works in counter mode. - pub fn task_count(&self) -> Task { + pub fn task_count<'s: 'd>(&self) -> Task<'s> { Task::from_reg(&T::regs().tasks_count) } @@ -258,14 +258,14 @@ impl<'d, T: Instance> Cc<'d, T> { /// Returns this CC register's CAPTURE task, for use with PPI. /// /// When triggered, this task will capture the current value of the timer's counter in this register. - pub fn task_capture(&self) -> Task { + pub fn task_capture<'s: 'd>(&self) -> Task<'s> { Task::from_reg(&T::regs().tasks_capture) } /// Returns this CC register's COMPARE event, for use with PPI. /// /// This event will fire when the timer's counter reaches the value in this CC register. - pub fn event_compare(&self) -> Event { + pub fn event_compare<'s: 'd>(&self) -> Event<'s> { Event::from_reg(&T::regs().events_compare[self.n]) } From ab7fcf1d5bf0a73cd86cabcb599e9f9e8f0b08ce Mon Sep 17 00:00:00 2001 From: Cameron Date: Wed, 5 Jul 2023 09:23:39 +0200 Subject: [PATCH 042/148] Removed unnecessary changes --- embassy-nrf/src/buffered_uarte.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 8fc3b4b9..b038fe59 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -352,13 +352,12 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { s.rx_ppi_ch.store(ppi_ch2.number() as u8, Ordering::Relaxed); let mut ppi_group = PpiGroup::new(ppi_group); - let ppi_group_channel_disable_all_task = ppi_group.task_disable_all(); - + let mut ppi_ch2 = Ppi::new_one_to_two( ppi_ch2, Event::from_reg(&r.events_endrx), Task::from_reg(&r.tasks_startrx), - ppi_group_channel_disable_all_task, + ppi_group.task_disable_all(), ); ppi_ch2.disable(); ppi_group.add_channel(&ppi_ch2); From 7d3eb6463a03f16674237ed7aa0a085dc6070207 Mon Sep 17 00:00:00 2001 From: Cameron Date: Wed, 5 Jul 2023 11:34:33 +0200 Subject: [PATCH 043/148] Removed unnecessary space --- embassy-nrf/src/buffered_uarte.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index b038fe59..9bc1c1e7 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -352,7 +352,6 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { s.rx_ppi_ch.store(ppi_ch2.number() as u8, Ordering::Relaxed); let mut ppi_group = PpiGroup::new(ppi_group); - let mut ppi_ch2 = Ppi::new_one_to_two( ppi_ch2, Event::from_reg(&r.events_endrx), From a0dc87d64ec75b6236abb60f93815f6d5c621de5 Mon Sep 17 00:00:00 2001 From: Rasmus Pedersen Date: Wed, 5 Jul 2023 14:07:05 +0200 Subject: [PATCH 044/148] Remove semicolon in time driver example struct declaration The semicolon is not allowed with struct declarations with braces. The doc test compiles fine for some reason!? --- embassy-time/src/driver.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-time/src/driver.rs b/embassy-time/src/driver.rs index d6436369..5fe7beca 100644 --- a/embassy-time/src/driver.rs +++ b/embassy-time/src/driver.rs @@ -36,7 +36,7 @@ //! ``` //! use embassy_time::driver::{Driver, AlarmHandle}; //! -//! struct MyDriver{}; // not public! +//! struct MyDriver{} // not public! //! embassy_time::time_driver_impl!(static DRIVER: MyDriver = MyDriver{}); //! //! impl Driver for MyDriver { From 8ee2f50b8c10dd86ec97e2d51110c9042d563075 Mon Sep 17 00:00:00 2001 From: Cameron Date: Wed, 5 Jul 2023 19:01:28 +0200 Subject: [PATCH 045/148] Removed unnecessary lifetime naming --- embassy-nrf/src/gpiote.rs | 8 ++++---- embassy-nrf/src/ppi/mod.rs | 4 ++-- embassy-nrf/src/pwm.rs | 22 +++++++++++----------- embassy-nrf/src/timer.rs | 12 ++++++------ 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 21d0d956..6550f2ab 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -221,7 +221,7 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> { } /// Returns the IN event, for use with PPI. - pub fn event_in(&self) -> Event { + pub fn event_in(&self) -> Event<'d> { let g = regs(); Event::from_reg(&g.events_in[self.ch.number()]) } @@ -292,21 +292,21 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> { } /// Returns the OUT task, for use with PPI. - pub fn task_out(&self) -> Task { + pub fn task_out(&self) -> Task<'d> { let g = regs(); Task::from_reg(&g.tasks_out[self.ch.number()]) } /// Returns the CLR task, for use with PPI. #[cfg(not(feature = "nrf51"))] - pub fn task_clr(&self) -> Task { + pub fn task_clr(&self) -> Task<'d> { let g = regs(); Task::from_reg(&g.tasks_clr[self.ch.number()]) } /// Returns the SET task, for use with PPI. #[cfg(not(feature = "nrf51"))] - pub fn task_set(&self) -> Task { + pub fn task_set(&self) -> Task<'d> { let g = regs(); Task::from_reg(&g.tasks_set[self.ch.number()]) } diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs index c2bc0f58..3be965ab 100644 --- a/embassy-nrf/src/ppi/mod.rs +++ b/embassy-nrf/src/ppi/mod.rs @@ -96,7 +96,7 @@ impl<'d, G: Group> PpiGroup<'d, G> { /// Get a reference to the "enable all" task. /// /// When triggered, it will enable all the channels in this group. - pub fn task_enable_all<'s: 'd>(&'d self) -> Task<'s> { + pub fn task_enable_all(&self) -> Task<'d> { let n = self.g.number(); Task::from_reg(®s().tasks_chg[n].en) } @@ -104,7 +104,7 @@ impl<'d, G: Group> PpiGroup<'d, G> { /// Get a reference to the "disable all" task. /// /// When triggered, it will disable all the channels in this group. - pub fn task_disable_all<'s: 'd>(&self) -> Task<'s> { + pub fn task_disable_all(&self) -> Task<'d> { let n = self.g.number(); Task::from_reg(®s().tasks_chg[n].dis) } diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index 363a255d..c8c81fa0 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs @@ -181,7 +181,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { /// Returns reference to `Stopped` event endpoint for PPI. #[inline(always)] - pub fn event_stopped(&self) -> Event { + pub fn event_stopped(&self) -> Event<'d> { let r = T::regs(); Event::from_reg(&r.events_stopped) @@ -189,7 +189,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { /// Returns reference to `LoopsDone` event endpoint for PPI. #[inline(always)] - pub fn event_loops_done(&self) -> Event { + pub fn event_loops_done(&self) -> Event<'d> { let r = T::regs(); Event::from_reg(&r.events_loopsdone) @@ -197,7 +197,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { /// Returns reference to `PwmPeriodEnd` event endpoint for PPI. #[inline(always)] - pub fn event_pwm_period_end(&self) -> Event { + pub fn event_pwm_period_end(&self) -> Event<'d> { let r = T::regs(); Event::from_reg(&r.events_pwmperiodend) @@ -205,7 +205,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { /// Returns reference to `Seq0 End` event endpoint for PPI. #[inline(always)] - pub fn event_seq_end(&self) -> Event { + pub fn event_seq_end(&self) -> Event<'d> { let r = T::regs(); Event::from_reg(&r.events_seqend[0]) @@ -213,7 +213,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { /// Returns reference to `Seq1 End` event endpoint for PPI. #[inline(always)] - pub fn event_seq1_end(&self) -> Event { + pub fn event_seq1_end(&self) -> Event<'d> { let r = T::regs(); Event::from_reg(&r.events_seqend[1]) @@ -221,7 +221,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { /// Returns reference to `Seq0 Started` event endpoint for PPI. #[inline(always)] - pub fn event_seq0_started(&self) -> Event { + pub fn event_seq0_started(&self) -> Event<'d> { let r = T::regs(); Event::from_reg(&r.events_seqstarted[0]) @@ -229,7 +229,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { /// Returns reference to `Seq1 Started` event endpoint for PPI. #[inline(always)] - pub fn event_seq1_started(&self) -> Event { + pub fn event_seq1_started(&self) -> Event<'d> { let r = T::regs(); Event::from_reg(&r.events_seqstarted[1]) @@ -240,7 +240,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { /// /// Interacting with the sequence while it runs puts it in an unknown state #[inline(always)] - pub unsafe fn task_start_seq0(&self) -> Task { + pub unsafe fn task_start_seq0(&self) -> Task<'d> { let r = T::regs(); Task::from_reg(&r.tasks_seqstart[0]) @@ -251,7 +251,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { /// /// Interacting with the sequence while it runs puts it in an unknown state #[inline(always)] - pub unsafe fn task_start_seq1(&self) -> Task { + pub unsafe fn task_start_seq1(&self) -> Task<'d> { let r = T::regs(); Task::from_reg(&r.tasks_seqstart[1]) @@ -262,7 +262,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { /// /// Interacting with the sequence while it runs puts it in an unknown state #[inline(always)] - pub unsafe fn task_next_step(&self) -> Task { + pub unsafe fn task_next_step(&self) -> Task<'d> { let r = T::regs(); Task::from_reg(&r.tasks_nextstep) @@ -273,7 +273,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> { /// /// Interacting with the sequence while it runs puts it in an unknown state #[inline(always)] - pub unsafe fn task_stop(&self) -> Task { + pub unsafe fn task_stop(&self) -> Task<'d> { let r = T::regs(); Task::from_reg(&r.tasks_stop) diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index fed576c3..04748238 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs @@ -168,21 +168,21 @@ impl<'d, T: Instance> Timer<'d, T> { /// Returns the START task, for use with PPI. /// /// When triggered, this task starts the timer. - pub fn task_start<'s: 'd>(&self) -> Task<'s> { + pub fn task_start(&self) -> Task<'d> { Task::from_reg(&T::regs().tasks_start) } /// Returns the STOP task, for use with PPI. /// /// When triggered, this task stops the timer. - pub fn task_stop<'s: 'd>(&self) -> Task<'s> { + pub fn task_stop(&self) -> Task<'d> { Task::from_reg(&T::regs().tasks_stop) } /// Returns the CLEAR task, for use with PPI. /// /// When triggered, this task resets the timer's counter to 0. - pub fn task_clear<'s: 'd>(&self) -> Task<'s> { + pub fn task_clear(&self) -> Task<'d> { Task::from_reg(&T::regs().tasks_clear) } @@ -190,7 +190,7 @@ impl<'d, T: Instance> Timer<'d, T> { /// /// When triggered, this task increments the timer's counter by 1. /// Only works in counter mode. - pub fn task_count<'s: 'd>(&self) -> Task<'s> { + pub fn task_count(&self) -> Task<'d> { Task::from_reg(&T::regs().tasks_count) } @@ -258,14 +258,14 @@ impl<'d, T: Instance> Cc<'d, T> { /// Returns this CC register's CAPTURE task, for use with PPI. /// /// When triggered, this task will capture the current value of the timer's counter in this register. - pub fn task_capture<'s: 'd>(&self) -> Task<'s> { + pub fn task_capture(&self) -> Task<'d> { Task::from_reg(&T::regs().tasks_capture) } /// Returns this CC register's COMPARE event, for use with PPI. /// /// This event will fire when the timer's counter reaches the value in this CC register. - pub fn event_compare<'s: 'd>(&self) -> Event<'s> { + pub fn event_compare(&self) -> Event<'d> { Event::from_reg(&T::regs().events_compare[self.n]) } From fb3e6a2b40abcd14dcaa1ba2ba91a46cbc1b0ed5 Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Wed, 5 Jul 2023 19:10:16 +0200 Subject: [PATCH 046/148] Update embassy-nrf/src/ppi/mod.rs Co-authored-by: Dario Nieuwenhuis --- embassy-nrf/src/ppi/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs index 3be965ab..568f7641 100644 --- a/embassy-nrf/src/ppi/mod.rs +++ b/embassy-nrf/src/ppi/mod.rs @@ -128,7 +128,7 @@ const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::(); #[derive(PartialEq, Eq, Clone, Copy)] pub struct Task<'d>(NonNull, PhantomData<&'d ()>); -impl<'d> Task<'_> { +impl<'d> Task<'d> { /// Create a new `Task` from a task register pointer /// /// # Safety From 67c4d165c7e9b7a490bf220246be783c7ada7f02 Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Wed, 5 Jul 2023 19:10:22 +0200 Subject: [PATCH 047/148] Update embassy-nrf/src/ppi/ppi.rs Co-authored-by: Dario Nieuwenhuis --- embassy-nrf/src/ppi/ppi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-nrf/src/ppi/ppi.rs b/embassy-nrf/src/ppi/ppi.rs index d0a70b85..2b9926e2 100644 --- a/embassy-nrf/src/ppi/ppi.rs +++ b/embassy-nrf/src/ppi/ppi.rs @@ -8,7 +8,7 @@ impl<'d> Task<'_> { self.0.as_ptr() as _ } } -impl<'d> Event<'_> { +impl<'d> Event<'d> { fn reg_val(&self) -> u32 { self.0.as_ptr() as _ } From 082147939d7e123994485c8a87daedf577905002 Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Wed, 5 Jul 2023 19:10:30 +0200 Subject: [PATCH 048/148] Update embassy-nrf/src/ppi/ppi.rs Co-authored-by: Dario Nieuwenhuis --- embassy-nrf/src/ppi/ppi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-nrf/src/ppi/ppi.rs b/embassy-nrf/src/ppi/ppi.rs index 2b9926e2..1fe89862 100644 --- a/embassy-nrf/src/ppi/ppi.rs +++ b/embassy-nrf/src/ppi/ppi.rs @@ -3,7 +3,7 @@ use embassy_hal_common::into_ref; use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task}; use crate::{pac, Peripheral}; -impl<'d> Task<'_> { +impl<'d> Task<'d> { fn reg_val(&self) -> u32 { self.0.as_ptr() as _ } From d7ecf6f59394ff1ca322a096b7405c8f552d4c44 Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Wed, 5 Jul 2023 19:10:43 +0200 Subject: [PATCH 049/148] Update embassy-nrf/src/ppi/mod.rs Co-authored-by: Dario Nieuwenhuis --- embassy-nrf/src/ppi/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs index 568f7641..ff6593bd 100644 --- a/embassy-nrf/src/ppi/mod.rs +++ b/embassy-nrf/src/ppi/mod.rs @@ -168,7 +168,7 @@ unsafe impl Send for Task<'_> {} #[derive(PartialEq, Eq, Clone, Copy)] pub struct Event<'d>(NonNull, PhantomData<&'d ()>); -impl<'d> Event<'_> { +impl<'d> Event<'d> { /// Create a new `Event` from an event register pointer /// /// # Safety From d1711036dba286ef0b629a3ab7e249fd855ea772 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 5 Jul 2023 19:13:46 +0200 Subject: [PATCH 050/148] stm32-wpan: fix wrong src_base --- embassy-stm32-wpan/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 4b830cab..6d4027fc 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" license = "MIT OR Apache-2.0" [package.metadata.embassy_docs] -src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-wpan-v$VERSION/embassy-stm32-wpan/src" -src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32-wpan/src" +src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-wpan-v$VERSION/embassy-stm32-wpan/src/" +src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32-wpan/src/" target = "thumbv7em-none-eabihf" features = ["stm32wb55rg"] From c6cd69887c64e22575442359040a890f32719295 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 5 Jul 2023 19:14:11 +0200 Subject: [PATCH 051/148] Downgrade nightly. Newer nightlies have a bad perf regression https://github.com/rust-lang/rust/issues/113372 --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index c201d8bd..5db74c7a 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-07-03" +channel = "nightly-2023-06-28" components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] targets = [ "thumbv7em-none-eabi", From a42ac86f1b71700632b77196ad506587774ae976 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 5 Jul 2023 19:16:45 +0200 Subject: [PATCH 052/148] Remove wifi envvars. They're annoying, they cause rust-analyzer errors when opening the examples. --- ci.sh | 4 ---- cyw43/README.md | 2 +- examples/nrf52840/src/bin/wifi_esp_hosted.rs | 5 ++++- examples/rp/src/bin/wifi_tcp_server.rs | 7 +++++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ci.sh b/ci.sh index a03efb85..376cc8f4 100755 --- a/ci.sh +++ b/ci.sh @@ -5,10 +5,6 @@ set -euo pipefail export RUSTFLAGS=-Dwarnings export DEFMT_LOG=trace,embassy_net_esp_hosted=debug,cyw43=info,cyw43_pio=info,smoltcp=info -# needed by wifi examples -export WIFI_NETWORK=x -export WIFI_PASSWORD=x - TARGET=$(rustc -vV | sed -n 's|host: ||p') BUILD_EXTRA="" diff --git a/cyw43/README.md b/cyw43/README.md index e4a81410..5b8f3cf4 100644 --- a/cyw43/README.md +++ b/cyw43/README.md @@ -30,7 +30,7 @@ TODO: ### Example 2: Create an access point (IP and credentials in the code) - `cargo run --release --bin wifi_ap_tcp_server` ### Example 3: Connect to an existing network and create a server -- `WIFI_NETWORK=MyWifiNetwork WIFI_PASSWORD=MyWifiPassword cargo run --release --bin wifi_tcp_server` +- `cargo run --release --bin wifi_tcp_server` After a few seconds, you should see that DHCP picks up an IP address like this ``` diff --git a/examples/nrf52840/src/bin/wifi_esp_hosted.rs b/examples/nrf52840/src/bin/wifi_esp_hosted.rs index f7496703..112e41bc 100644 --- a/examples/nrf52840/src/bin/wifi_esp_hosted.rs +++ b/examples/nrf52840/src/bin/wifi_esp_hosted.rs @@ -16,6 +16,9 @@ use embedded_io::asynch::Write; use static_cell::make_static; use {defmt_rtt as _, embassy_net_esp_hosted as hosted, panic_probe as _}; +const WIFI_NETWORK: &str = "EmbassyTest"; +const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; + bind_interrupts!(struct Irqs { SPIM3 => spim::InterruptHandler; RNG => embassy_nrf::rng::InterruptHandler; @@ -70,7 +73,7 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(wifi_task(runner))); control.init().await; - control.join(env!("WIFI_NETWORK"), env!("WIFI_PASSWORD")).await; + control.join(WIFI_NETWORK, WIFI_PASSWORD).await; let config = embassy_net::Config::dhcpv4(Default::default()); // let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index e9d1079a..197535f4 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -19,6 +19,9 @@ use embedded_io::asynch::Write; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; +const WIFI_NETWORK: &str = "EmbassyTest"; +const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; + #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -82,8 +85,8 @@ async fn main(spawner: Spawner) { unwrap!(spawner.spawn(net_task(stack))); loop { - //control.join_open(env!("WIFI_NETWORK")).await; - match control.join_wpa2(env!("WIFI_NETWORK"), env!("WIFI_PASSWORD")).await { + //control.join_open(WIFI_NETWORK).await; + match control.join_wpa2(WIFI_NETWORK, WIFI_PASSWORD).await { Ok(_) => break, Err(err) => { info!("join failed with status={}", err.status); From d1372869813e268a19e83819c7f1a0631d2f24d1 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 5 Jul 2023 23:54:45 +0200 Subject: [PATCH 053/148] Release embassy-time v0.1.2 --- cyw43/Cargo.toml | 2 +- embassy-embedded-hal/Cargo.toml | 2 +- embassy-executor/Cargo.toml | 4 ++-- embassy-lora/Cargo.toml | 2 +- embassy-net-esp-hosted/Cargo.toml | 2 +- embassy-net-w5500/Cargo.toml | 6 +++--- embassy-net/Cargo.toml | 2 +- embassy-nrf/Cargo.toml | 18 +++++++++--------- embassy-rp/Cargo.toml | 2 +- embassy-stm32-wpan/Cargo.toml | 2 +- embassy-stm32/Cargo.toml | 2 +- embassy-time/CHANGELOG.md | 5 +++++ 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 | 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/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 +- 51 files changed, 66 insertions(+), 61 deletions(-) diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml index 7d2f9dfd..50fb7c5d 100644 --- a/cyw43/Cargo.toml +++ b/cyw43/Cargo.toml @@ -11,7 +11,7 @@ log = ["dep:log"] firmware-logs = [] [dependencies] -embassy-time = { version = "0.1.0", path = "../embassy-time"} +embassy-time = { version = "0.1.2", 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"} diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml index 2d11dc3c..bba3d48b 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.0", path = "../embassy-time", optional = true } +embassy-time = { version = "0.1.2", 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 1e5494ef..590718e3 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml @@ -61,8 +61,8 @@ 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-time = { version = "0.1.0", path = "../embassy-time", optional = true} +embassy-macros = { version = "0.2.0", path = "../embassy-macros" } +embassy-time = { version = "0.1.2", 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 dc44f96d..e4524af5 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.0", path = "../embassy-time" } +embassy-time = { version = "0.1.2", path = "../embassy-time" } 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-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml index a52570f5..26f5b40b 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.0", path = "../embassy-time" } +embassy-time = { version = "0.1.2", 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"} diff --git a/embassy-net-w5500/Cargo.toml b/embassy-net-w5500/Cargo.toml index 41d41111..8972b814 100644 --- a/embassy-net-w5500/Cargo.toml +++ b/embassy-net-w5500/Cargo.toml @@ -10,9 +10,9 @@ edition = "2021" [dependencies] embedded-hal = { version = "1.0.0-alpha.11" } embedded-hal-async = { version = "=0.2.0-alpha.2" } -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" } +embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel" } +embassy-time = { version = "0.1.2", path = "../embassy-time" } +embassy-futures = { version = "0.1.0", path = "../embassy-futures" } defmt = { version = "0.3", optional = true } [package.metadata.embassy_docs] diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index e89039da..6dc429dd 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -50,7 +50,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.0", path = "../embassy-time" } +embassy-time = { version = "0.1.2", path = "../embassy-time" } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embedded-io = { version = "0.4.0", optional = true } diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index ae76af3e..57dd22f1 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -91,7 +91,7 @@ _dppi = [] _gpio-p1 = [] [dependencies] -embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } +embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-3"] } embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } @@ -106,7 +106,7 @@ defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } cortex-m-rt = ">=0.6.15,<0.8" cortex-m = "0.7.6" -futures = { version = "0.3.17", default-features = false } +futures = { version = "0.3.17", default-features = false } critical-section = "1.1" rand_core = "0.6.3" fixed = "1.10.0" @@ -114,13 +114,13 @@ embedded-storage = "0.3.0" embedded-storage-async = { version = "0.4.0", optional = true } cfg-if = "1.0.0" -nrf52805-pac = { version = "0.12.0", optional = true } -nrf52810-pac = { version = "0.12.0", optional = true } -nrf52811-pac = { version = "0.12.0", optional = true } -nrf52820-pac = { version = "0.12.0", optional = true } -nrf52832-pac = { version = "0.12.0", optional = true } -nrf52833-pac = { version = "0.12.0", optional = true } -nrf52840-pac = { version = "0.12.0", optional = true } +nrf52805-pac = { version = "0.12.0", optional = true } +nrf52810-pac = { version = "0.12.0", optional = true } +nrf52811-pac = { version = "0.12.0", optional = true } +nrf52820-pac = { version = "0.12.0", optional = true } +nrf52832-pac = { version = "0.12.0", optional = true } +nrf52833-pac = { version = "0.12.0", optional = true } +nrf52840-pac = { version = "0.12.0", optional = true } nrf5340-app-pac = { version = "0.12.0", optional = true } nrf5340-net-pac = { version = "0.12.0", optional = true } nrf9160-pac = { version = "0.12.0", optional = true } diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index a06831a9..8f3ed885 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -56,7 +56,7 @@ unstable-traits = ["embedded-hal-1", "embedded-hal-nb"] [dependencies] embassy-sync = { version = "0.2.0", path = "../embassy-sync" } -embassy-time = { version = "0.1.0", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] } +embassy-time = { version = "0.1.2", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-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 6d4027fc..5141f9bd 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.0", path = "../embassy-time", optional = true } +embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 04514963..ec934e8b 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.0", path = "../embassy-time", optional = true } +embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-4"] } embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } diff --git a/embassy-time/CHANGELOG.md b/embassy-time/CHANGELOG.md index f4a7860e..26640d93 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.2 - 2023-07-05 + +- Update `embedded-hal-async` to `0.2.0-alpha.2`. +- Update `embedded-hal v1` to `1.0.0-alpha.11`. (Note: v0.2 support is kept unchanged). + ## 0.1.1 - 2023-04-13 - Update `embedded-hal-async` to `0.2.0-alpha.1` (uses `async fn` in traits). diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index 0213eef0..0ff0e3be 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "embassy-time" -version = "0.1.1" +version = "0.1.2" 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 b98f73f3..2a0cf781 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.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] } +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"] } 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 007b6839..95b2da95 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.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] } -embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] } +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"] } 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 5b3faf8f..3b0fc4d9 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.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +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"] } 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 b6a6f9cd..323b4ab2 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.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +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"] } 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 0a7e19b1..b2abdc89 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.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +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"] } 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 998df4dc..0b7e72d5 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.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +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"] } 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 10b58c17..5f3f365c 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.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +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"] } 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 713a6527..44eb5aba 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.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +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"] } 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 4c8bbd73..fdad5506 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.2.0", path = "../../../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] } +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"] } 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 a3acc56b..30b67b7b 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.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace", "rtos-trace-interrupt", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../embassy-time" } +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"] } 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 0f9048b0..ded3b7db 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.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "generic-queue"] } +embassy-time = { version = "0.1.2", 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 2ccd5045..7b9c371b 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -29,7 +29,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.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } +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 } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "msos-descriptor",], optional = true } diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index efb66bae..f1d45f33 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -14,7 +14,7 @@ embassy-executor = { version = "0.2.0", path = "../../embassy-executor", feature "defmt", "integrated-timers", ] } -embassy-time = { version = "0.1.0", path = "../../embassy-time", features = [ +embassy-time = { version = "0.1.2", path = "../../embassy-time", features = [ "defmt", "defmt-timestamp-uptime", ] } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 17ebea86..7c5a9dfb 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.2.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 = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] } +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"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] } diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 878ad8c5..92933ab5 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.2.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "std", "nightly"] } +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", "unstable-traits", "proto-ipv6"] } embassy-net-driver = { version = "0.1.0", path = "../../embassy-net-driver" } embedded-io = { version = "0.4.0", features = ["async", "std", "futures"] } diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index 43f43252..26837abe 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", 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"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] } defmt = "0.3" diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 8d2248ed..b7b5eaa9 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -14,6 +14,6 @@ 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-time = { version = "0.1.0", 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"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f091rc", "time-driver-any", "exti", "unstable-pac"] } static_cell = { version = "1.1", features = ["nightly"]} diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index d34fd439..29cad5b6 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", 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"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any", "unstable-traits" ] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index 5e3e0d0f..652210c7 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", 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"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } defmt = "0.3" diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 29ab2009..489d0ff4 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/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.2.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-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 7ecb64fc..c1c82136 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers", "arch-cortex-m", "executor-thread", "executor-interrupt"] } -embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } +embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "embedded-sdmmc", "chrono"] } 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 657251c5..84d7b79c 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", 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"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] } embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } embedded-io = { version = "0.4.0", features = ["async"] } diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index c5245757..c88282d9 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", 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"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] } defmt = "0.3" diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index fbfbc640..18bd03c3 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", 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"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 789ef59c..227bc28b 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } +embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h563zi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits", "proto-ipv6"] } embedded-io = { version = "0.4.0", features = ["async"] } diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 04a2baab..768702fa 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } +embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits", "proto-ipv6"] } embedded-io = { version = "0.4.0", features = ["async"] } diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 988fd3a7..747cec7b 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -12,7 +12,7 @@ nightly = ["embassy-stm32/nightly", "embassy-time/nightly", "embassy-time/unstab [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", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", 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"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] } embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt"], optional = true } lora-phy = { version = "1", optional = true } diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 93d48abe..dcca1cc3 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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", 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"] } 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 dca052c2..c5555851 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", 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"] } embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "time-driver-any", "exti", "unstable-traits", "chrono"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 6035c291..54911482 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", 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"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index e2318c3d..835e3294 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", 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"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index fbb2d918..203ca148 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", 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"] } 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"] } diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 75a5f1c4..99f68387 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti"] } 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 437e443a..3679e385 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.2.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "wasm", "nightly"] } +embassy-time = { version = "0.1.2", 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 247287e4..7ce51aa5 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.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "nightly", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "nightly", "unstable-traits", "defmt-timestamp-uptime"] } +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 = { version = "0.4.0", features = ["async"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "nightly"] } diff --git a/tests/riscv32/Cargo.toml b/tests/riscv32/Cargo.toml index 81bfdfab..61f886c0 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.2.0", path = "../../embassy-executor", features = ["arch-riscv32", "nightly", "executor-thread"] } -embassy-time = { version = "0.1.0", path = "../../embassy-time" } +embassy-time = { version = "0.1.2", 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 f1b48e74..368d4acf 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.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt"] } +embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt"] } 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 c69af6d5..4fd4a6d0 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -27,7 +27,7 @@ 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-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] } +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" } embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg", "ble"] } From 47305c2bf24c05b4956d9491478dfa53df09c47f Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 6 Jul 2023 02:32:49 +0200 Subject: [PATCH 054/148] ci: build doc with 4 threads instead of 6, to avoid running out of disk space. --- .github/ci/doc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index e4d83e4b..9e9c78a4 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -6,7 +6,7 @@ set -euo pipefail export RUSTUP_HOME=/ci/cache/rustup export CARGO_HOME=/ci/cache/cargo export CARGO_TARGET_DIR=/ci/cache/target -export BUILDER_THREADS=6 +export BUILDER_THREADS=4 export BUILDER_COMPRESS=true # force rustup to download the toolchain before starting building. From ffeb40ff43ea52d0df5d5e6e807ecb87eafdf0c8 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 6 Jul 2023 13:49:19 +0200 Subject: [PATCH 055/148] stm32/otg: change some info logs to trace. --- embassy-stm32/src/usb_otg/usb.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs index 6783db28..492b7758 100644 --- a/embassy-stm32/src/usb_otg/usb.rs +++ b/embassy-stm32/src/usb_otg/usb.rs @@ -648,7 +648,7 @@ impl<'d, T: Instance> Bus<'d, T> { let r = T::regs(); let core_id = r.cid().read().0; - info!("Core id {:08x}", core_id); + trace!("Core id {:08x}", core_id); // Wait for AHB ready. while !r.grstctl().read().ahbidl() {} @@ -1214,7 +1214,7 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { let diepctl = r.diepctl(index).read(); let dtxfsts = r.dtxfsts(index).read(); - info!("diepctl {:08x} ftxfsts {:08x}", diepctl.0, dtxfsts.0); + trace!("diepctl {:08x} ftxfsts {:08x}", diepctl.0, dtxfsts.0); if !diepctl.usbaep() { trace!("write ep={:?} wait for prev: error disabled", self.info.addr); Poll::Ready(Err(EndpointError::Disabled)) From f8d608093f51ab6fe97b32c7a23bf131a10b6f9c Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 7 Jul 2023 03:41:27 +0200 Subject: [PATCH 056/148] stm32/otg: implement `EndpointError::Disabled` for reads. It was implemented only for writes. --- embassy-stm32/src/usb_otg/usb.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs index 492b7758..d0284746 100644 --- a/embassy-stm32/src/usb_otg/usb.rs +++ b/embassy-stm32/src/usb_otg/usb.rs @@ -1154,14 +1154,22 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointOut for Endpoint<'d, T, Out> { trace!("read start len={}", buf.len()); poll_fn(|cx| { + let r = T::regs(); let index = self.info.addr.index(); let state = T::state(); state.ep_out_wakers[index].register(cx.waker()); + let doepctl = r.doepctl(index).read(); + trace!("read ep={:?}: doepctl {:08x}", self.info.addr, doepctl.0,); + if !doepctl.usbaep() { + trace!("read ep={:?} error disabled", self.info.addr); + return Poll::Ready(Err(EndpointError::Disabled)); + } + let len = state.ep_out_size[index].load(Ordering::Relaxed); if len != EP_OUT_BUFFER_EMPTY { - trace!("read done len={}", len); + trace!("read ep={:?} done len={}", self.info.addr, len); if len as usize > buf.len() { return Poll::Ready(Err(EndpointError::BufferOverflow)); @@ -1214,7 +1222,12 @@ impl<'d, T: Instance> embassy_usb_driver::EndpointIn for Endpoint<'d, T, In> { let diepctl = r.diepctl(index).read(); let dtxfsts = r.dtxfsts(index).read(); - trace!("diepctl {:08x} ftxfsts {:08x}", diepctl.0, dtxfsts.0); + trace!( + "write ep={:?}: diepctl {:08x} ftxfsts {:08x}", + self.info.addr, + diepctl.0, + dtxfsts.0 + ); if !diepctl.usbaep() { trace!("write ep={:?} wait for prev: error disabled", self.info.addr); Poll::Ready(Err(EndpointError::Disabled)) From 4b63829110b8ef314d22d78c160f54e6ae98634c Mon Sep 17 00:00:00 2001 From: pennae Date: Fri, 7 Jul 2023 04:30:46 +0200 Subject: [PATCH 057/148] rp/pio: use bind_interrupts for irqs closes #1338 --- embassy-rp/src/lib.rs | 1 - embassy-rp/src/pio.rs | 78 ++++++++++------------- examples/rp/src/bin/pio_async.rs | 9 ++- examples/rp/src/bin/pio_dma.rs | 11 +++- examples/rp/src/bin/pio_hd44780.rs | 15 +++-- examples/rp/src/bin/pio_ws2812.rs | 13 +++- examples/rp/src/bin/wifi_ap_tcp_server.rs | 9 ++- examples/rp/src/bin/wifi_blinky.rs | 9 ++- examples/rp/src/bin/wifi_scan.rs | 9 ++- examples/rp/src/bin/wifi_tcp_server.rs | 9 ++- tests/rp/Cargo.toml | 2 + tests/rp/src/bin/cyw43-perf.rs | 10 ++- tests/rp/src/bin/pio_irq.rs | 55 ++++++++++++++++ 13 files changed, 160 insertions(+), 70 deletions(-) create mode 100644 tests/rp/src/bin/pio_irq.rs diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 4fd3cb46..4f205a16 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -252,7 +252,6 @@ pub fn init(config: config::Config) -> Peripherals { #[cfg(feature = "time-driver")] timer::init(); dma::init(); - pio::init(); gpio::init(); } diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs index 30648e8e..72a2f44e 100644 --- a/embassy-rp/src/pio.rs +++ b/embassy-rp/src/pio.rs @@ -16,12 +16,12 @@ use pio::{SideSet, Wrap}; use crate::dma::{Channel, Transfer, Word}; use crate::gpio::sealed::Pin as SealedPin; use crate::gpio::{self, AnyPin, Drive, Level, Pull, SlewRate}; -use crate::interrupt::InterruptExt; +use crate::interrupt::typelevel::{Binding, Handler, Interrupt}; use crate::pac::dma::vals::TreqSel; use crate::relocate::RelocatedProgram; -use crate::{interrupt, pac, peripherals, pio_instr_util, RegExt}; +use crate::{pac, peripherals, pio_instr_util, RegExt}; -struct Wakers([AtomicWaker; 12]); +pub struct Wakers([AtomicWaker; 12]); impl Wakers { #[inline(always)] @@ -38,10 +38,6 @@ impl Wakers { } } -const NEW_AW: AtomicWaker = AtomicWaker::new(); -const PIO_WAKERS_INIT: Wakers = Wakers([NEW_AW; 12]); -static WAKERS: [Wakers; 2] = [PIO_WAKERS_INIT; 2]; - #[derive(Clone, Copy, PartialEq, Eq, Default, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(u8)] @@ -85,42 +81,20 @@ const RXNEMPTY_MASK: u32 = 1 << 0; const TXNFULL_MASK: u32 = 1 << 4; const SMIRQ_MASK: u32 = 1 << 8; -#[cfg(feature = "rt")] -#[interrupt] -fn PIO0_IRQ_0() { - use crate::pac; - let ints = pac::PIO0.irqs(0).ints().read().0; - for bit in 0..12 { - if ints & (1 << bit) != 0 { - WAKERS[0].0[bit].wake(); - } - } - pac::PIO0.irqs(0).inte().write_clear(|m| m.0 = ints); +pub struct InterruptHandler { + _pio: PhantomData, } -#[cfg(feature = "rt")] -#[interrupt] -fn PIO1_IRQ_0() { - use crate::pac; - let ints = pac::PIO1.irqs(0).ints().read().0; - for bit in 0..12 { - if ints & (1 << bit) != 0 { - WAKERS[1].0[bit].wake(); +impl Handler for InterruptHandler { + unsafe fn on_interrupt() { + let ints = PIO::PIO.irqs(0).ints().read().0; + for bit in 0..12 { + if ints & (1 << bit) != 0 { + PIO::wakers().0[bit].wake(); + } } + PIO::PIO.irqs(0).inte().write_clear(|m| m.0 = ints); } - pac::PIO1.irqs(0).inte().write_clear(|m| m.0 = ints); -} - -pub(crate) unsafe fn init() { - interrupt::PIO0_IRQ_0.disable(); - interrupt::PIO0_IRQ_0.set_priority(interrupt::Priority::P3); - pac::PIO0.irqs(0).inte().write(|m| m.0 = 0); - interrupt::PIO0_IRQ_0.enable(); - - interrupt::PIO1_IRQ_0.disable(); - interrupt::PIO1_IRQ_0.set_priority(interrupt::Priority::P3); - pac::PIO1.irqs(0).inte().write(|m| m.0 = 0); - interrupt::PIO1_IRQ_0.enable(); } /// Future that waits for TX-FIFO to become writable @@ -144,7 +118,7 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoOutFuture<'a, 'd, PI if self.get_mut().sm_tx.try_push(value) { Poll::Ready(()) } else { - WAKERS[PIO::PIO_NO as usize].fifo_out()[SM].register(cx.waker()); + PIO::wakers().fifo_out()[SM].register(cx.waker()); PIO::PIO.irqs(0).inte().write_set(|m| { m.0 = TXNFULL_MASK << SM; }); @@ -181,7 +155,7 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoInFuture<'a, 'd, PIO if let Some(v) = self.sm_rx.try_pull() { Poll::Ready(v) } else { - WAKERS[PIO::PIO_NO as usize].fifo_in()[SM].register(cx.waker()); + PIO::wakers().fifo_in()[SM].register(cx.waker()); PIO::PIO.irqs(0).inte().write_set(|m| { m.0 = RXNEMPTY_MASK << SM; }); @@ -217,7 +191,7 @@ impl<'a, 'd, PIO: Instance> Future for IrqFuture<'a, 'd, PIO> { return Poll::Ready(()); } - WAKERS[PIO::PIO_NO as usize].irq()[self.irq_no as usize].register(cx.waker()); + PIO::wakers().irq()[self.irq_no as usize].register(cx.waker()); PIO::PIO.irqs(0).inte().write_set(|m| { m.0 = SMIRQ_MASK << self.irq_no; }); @@ -949,9 +923,11 @@ pub struct Pio<'d, PIO: Instance> { } impl<'d, PIO: Instance> Pio<'d, PIO> { - pub fn new(_pio: impl Peripheral

+ 'd) -> Self { + pub fn new(_pio: impl Peripheral

+ 'd, _irq: impl Binding>) -> Self { PIO::state().users.store(5, Ordering::Release); PIO::state().used_pins.store(0, Ordering::Release); + PIO::Interrupt::unpend(); + unsafe { PIO::Interrupt::enable() }; Self { common: Common { instructions_used: 0, @@ -1017,6 +993,15 @@ mod sealed { const PIO_NO: u8; const PIO: &'static crate::pac::pio::Pio; const FUNCSEL: crate::pac::io::vals::Gpio0ctrlFuncsel; + type Interrupt: crate::interrupt::typelevel::Interrupt; + + #[inline] + fn wakers() -> &'static Wakers { + const NEW_AW: AtomicWaker = AtomicWaker::new(); + static WAKERS: Wakers = Wakers([NEW_AW; 12]); + + &WAKERS + } #[inline] fn state() -> &'static State { @@ -1033,18 +1018,19 @@ mod sealed { pub trait Instance: sealed::Instance + Sized + Unpin {} macro_rules! impl_pio { - ($name:ident, $pio:expr, $pac:ident, $funcsel:ident) => { + ($name:ident, $pio:expr, $pac:ident, $funcsel:ident, $irq:ident) => { impl sealed::Instance for peripherals::$name { const PIO_NO: u8 = $pio; const PIO: &'static pac::pio::Pio = &pac::$pac; const FUNCSEL: pac::io::vals::Gpio0ctrlFuncsel = pac::io::vals::Gpio0ctrlFuncsel::$funcsel; + type Interrupt = crate::interrupt::typelevel::$irq; } impl Instance for peripherals::$name {} }; } -impl_pio!(PIO0, 0, PIO0, PIO0_0); -impl_pio!(PIO1, 1, PIO1, PIO1_0); +impl_pio!(PIO0, 0, PIO0, PIO0_0, PIO0_IRQ_0); +impl_pio!(PIO1, 1, PIO1, PIO1_0, PIO1_IRQ_0); pub trait PioPin: sealed::PioPin + gpio::Pin {} diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 79eda1a0..69034c92 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -3,13 +3,18 @@ #![feature(type_alias_impl_trait)] use defmt::info; use embassy_executor::Spawner; +use embassy_rp::bind_interrupts; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{Common, Config, Irq, Pio, PioPin, ShiftDirection, StateMachine}; +use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine}; use embassy_rp::relocate::RelocatedProgram; use fixed::traits::ToFixed; use fixed_macro::types::U56F8; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 0>, pin: impl PioPin) { // Setup sm0 @@ -110,7 +115,7 @@ async fn main(spawner: Spawner) { mut sm1, mut sm2, .. - } = Pio::new(pio); + } = Pio::new(pio, Irqs); setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); setup_pio_task_sm1(&mut common, &mut sm1); diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 05c0ebb1..80c96355 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -4,13 +4,18 @@ use defmt::info; use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_rp::pio::{Config, Pio, ShiftConfig, ShiftDirection}; +use embassy_rp::peripherals::PIO0; +use embassy_rp::pio::{Config, InterruptHandler, Pio, ShiftConfig, ShiftDirection}; use embassy_rp::relocate::RelocatedProgram; -use embassy_rp::Peripheral; +use embassy_rp::{bind_interrupts, Peripheral}; use fixed::traits::ToFixed; use fixed_macro::types::U56F8; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + fn swap_nibbles(v: u32) -> u32 { let v = (v & 0x0f0f_0f0f) << 4 | (v & 0xf0f0_f0f0) >> 4; let v = (v & 0x00ff_00ff) << 8 | (v & 0xff00_ff00) >> 8; @@ -25,7 +30,7 @@ async fn main(_spawner: Spawner) { mut common, sm0: mut sm, .. - } = Pio::new(pio); + } = Pio::new(pio, Irqs); let prg = pio_proc::pio_asm!( ".origin 0", diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index bfc6c990..0a4514a6 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -7,13 +7,19 @@ use core::fmt::Write; use embassy_executor::Spawner; use embassy_rp::dma::{AnyChannel, Channel}; use embassy_rp::peripherals::PIO0; -use embassy_rp::pio::{Config, Direction, FifoJoin, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; +use embassy_rp::pio::{ + Config, Direction, FifoJoin, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, +}; use embassy_rp::pwm::{self, Pwm}; use embassy_rp::relocate::RelocatedProgram; -use embassy_rp::{into_ref, Peripheral, PeripheralRef}; +use embassy_rp::{bind_interrupts, into_ref, Peripheral, PeripheralRef}; use embassy_time::{Duration, Instant, Timer}; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(pub struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + #[embassy_executor::main] async fn main(_spawner: Spawner) { // this test assumes a 2x16 HD44780 display attached as follow: @@ -37,7 +43,7 @@ async fn main(_spawner: Spawner) { }); let mut hd = HD44780::new( - p.PIO0, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6, + p.PIO0, Irqs, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6, ) .await; @@ -72,6 +78,7 @@ pub struct HD44780<'l> { impl<'l> HD44780<'l> { pub async fn new( pio: impl Peripheral

+ 'l, + irq: Irqs, dma: impl Peripheral

+ 'l, rs: impl PioPin, rw: impl PioPin, @@ -88,7 +95,7 @@ impl<'l> HD44780<'l> { mut irq0, mut sm0, .. - } = Pio::new(pio); + } = Pio::new(pio, irq); // takes command words ( <0:4>) let prg = pio_proc::pio_asm!( diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs index 26422421..4a111e7a 100644 --- a/examples/rp/src/bin/pio_ws2812.rs +++ b/examples/rp/src/bin/pio_ws2812.rs @@ -5,15 +5,22 @@ use defmt::*; use embassy_executor::Spawner; use embassy_rp::dma::{AnyChannel, Channel}; -use embassy_rp::pio::{Common, Config, FifoJoin, Instance, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; +use embassy_rp::peripherals::PIO0; +use embassy_rp::pio::{ + Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, +}; use embassy_rp::relocate::RelocatedProgram; -use embassy_rp::{clocks, into_ref, Peripheral, PeripheralRef}; +use embassy_rp::{bind_interrupts, clocks, into_ref, Peripheral, PeripheralRef}; use embassy_time::{Duration, Timer}; use fixed::types::U24F8; use fixed_macro::fixed; use smart_leds::RGB8; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + pub struct Ws2812<'d, P: Instance, const S: usize, const N: usize> { dma: PeripheralRef<'d, AnyChannel>, sm: StateMachine<'d, P, S>, @@ -123,7 +130,7 @@ async fn main(_spawner: Spawner) { info!("Start"); let p = embassy_rp::init(Default::default()); - let Pio { mut common, sm0, .. } = Pio::new(p.PIO0); + let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs); // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit // feather boards for the 2040 both have one built in. diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 310e84d9..3e41f83b 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -11,14 +11,19 @@ use defmt::*; use embassy_executor::Spawner; use embassy_net::tcp::TcpSocket; use embassy_net::{Config, Stack, StackResources}; +use embassy_rp::bind_interrupts; use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; -use embassy_rp::pio::Pio; +use embassy_rp::pio::{InterruptHandler, Pio}; use embassy_time::Duration; use embedded_io::asynch::Write; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -49,7 +54,7 @@ async fn main(spawner: Spawner) { let pwr = Output::new(p.PIN_23, Level::Low); let cs = Output::new(p.PIN_25, Level::High); - let mut pio = Pio::new(p.PIO0); + let mut pio = Pio::new(p.PIO0, Irqs); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); let state = make_static!(cyw43::State::new()); diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs index bbcb1b5e..6eb207af 100644 --- a/examples/rp/src/bin/wifi_blinky.rs +++ b/examples/rp/src/bin/wifi_blinky.rs @@ -5,13 +5,18 @@ use cyw43_pio::PioSpi; use defmt::*; use embassy_executor::Spawner; +use embassy_rp::bind_interrupts; use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; -use embassy_rp::pio::Pio; +use embassy_rp::pio::{InterruptHandler, Pio}; use embassy_time::{Duration, Timer}; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -34,7 +39,7 @@ async fn main(spawner: Spawner) { let pwr = Output::new(p.PIN_23, Level::Low); let cs = Output::new(p.PIN_25, Level::High); - let mut pio = Pio::new(p.PIO0); + let mut pio = Pio::new(p.PIO0, Irqs); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); let state = make_static!(cyw43::State::new()); diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index 391e1228..aef18aa2 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs @@ -10,12 +10,17 @@ use cyw43_pio::PioSpi; use defmt::*; use embassy_executor::Spawner; use embassy_net::Stack; +use embassy_rp::bind_interrupts; use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; -use embassy_rp::pio::Pio; +use embassy_rp::pio::{InterruptHandler, Pio}; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + #[embassy_executor::task] async fn wifi_task( runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, @@ -46,7 +51,7 @@ async fn main(spawner: Spawner) { let pwr = Output::new(p.PIN_23, Level::Low); let cs = Output::new(p.PIN_25, Level::High); - let mut pio = Pio::new(p.PIO0); + let mut pio = Pio::new(p.PIO0, Irqs); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); let state = make_static!(cyw43::State::new()); diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 197535f4..4fce74a6 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -11,14 +11,19 @@ use defmt::*; use embassy_executor::Spawner; use embassy_net::tcp::TcpSocket; use embassy_net::{Config, Stack, StackResources}; +use embassy_rp::bind_interrupts; use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; -use embassy_rp::pio::Pio; +use embassy_rp::pio::{InterruptHandler, Pio}; use embassy_time::Duration; use embedded_io::asynch::Write; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + const WIFI_NETWORK: &str = "EmbassyTest"; const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; @@ -52,7 +57,7 @@ async fn main(spawner: Spawner) { let pwr = Output::new(p.PIN_23, Level::Low); let cs = Output::new(p.PIN_25, Level::High); - let mut pio = Pio::new(p.PIO0); + let mut pio = Pio::new(p.PIO0, Irqs); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); let state = make_static!(cyw43::State::new()); diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 368d4acf..f2c90278 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml @@ -29,6 +29,8 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa embedded-io = { version = "0.4.0", features = ["async"] } embedded-storage = { version = "0.3" } static_cell = { version = "1.1", features = ["nightly"]} +pio = "0.2" +pio-proc = "0.2" [profile.dev] debug = 2 diff --git a/tests/rp/src/bin/cyw43-perf.rs b/tests/rp/src/bin/cyw43-perf.rs index 1ecaab26..bc127e2e 100644 --- a/tests/rp/src/bin/cyw43-perf.rs +++ b/tests/rp/src/bin/cyw43-perf.rs @@ -12,12 +12,16 @@ use embassy_net::tcp::TcpSocket; use embassy_net::{Config, Ipv4Address, Stack, StackResources}; use embassy_rp::gpio::{Level, Output}; use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; -use embassy_rp::pio::Pio; -use embassy_rp::rom_data; +use embassy_rp::pio::{InterruptHandler, Pio}; +use embassy_rp::{bind_interrupts, rom_data}; use embassy_time::{with_timeout, Duration, Timer}; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + teleprobe_meta::timeout!(120); #[embassy_executor::task] @@ -51,7 +55,7 @@ async fn main(spawner: Spawner) { let pwr = Output::new(p.PIN_23, Level::Low); let cs = Output::new(p.PIN_25, Level::High); - let mut pio = Pio::new(p.PIO0); + let mut pio = Pio::new(p.PIO0, Irqs); let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); let state = make_static!(cyw43::State::new()); diff --git a/tests/rp/src/bin/pio_irq.rs b/tests/rp/src/bin/pio_irq.rs new file mode 100644 index 00000000..45004424 --- /dev/null +++ b/tests/rp/src/bin/pio_irq.rs @@ -0,0 +1,55 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +#[path = "../common.rs"] +mod common; + +use defmt::info; +use embassy_executor::Spawner; +use embassy_rp::bind_interrupts; +use embassy_rp::peripherals::PIO0; +use embassy_rp::pio::{Config, InterruptHandler, Pio}; +use embassy_rp::relocate::RelocatedProgram; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let pio = p.PIO0; + let Pio { + mut common, + sm0: mut sm, + irq_flags, + .. + } = Pio::new(pio, Irqs); + + let prg = pio_proc::pio_asm!( + "irq set 0", + "irq wait 0", + "irq set 1", + // pause execution here + "irq wait 1", + ); + + let relocated = RelocatedProgram::new(&prg.program); + let mut cfg = Config::default(); + cfg.use_program(&common.load_program(&relocated), &[]); + sm.set_config(&cfg); + sm.set_enable(true); + + // not using the wait futures on purpose because they clear the irq bits, + // and we want to see in which order they are set. + while !irq_flags.check(0) {} + cortex_m::asm::nop(); + assert!(!irq_flags.check(1)); + irq_flags.clear(0); + cortex_m::asm::nop(); + assert!(irq_flags.check(1)); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} From 151557fec38a454d0ff29de0e32914fed12869fd Mon Sep 17 00:00:00 2001 From: Roy Buitenhuis Date: Fri, 7 Jul 2023 16:38:56 +0200 Subject: [PATCH 058/148] Re-export smoltcp::wire::IpEndpoint --- embassy-net/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 840d7a09..0d0a986f 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -34,7 +34,7 @@ use smoltcp::socket::dhcpv4::{self, RetryConfig}; pub use smoltcp::wire::IpListenEndpoint; #[cfg(feature = "medium-ethernet")] pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; -pub use smoltcp::wire::{IpAddress, IpCidr}; +pub use smoltcp::wire::{IpAddress, IpCidr, IpEndpoint}; #[cfg(feature = "proto-ipv4")] pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr}; #[cfg(feature = "proto-ipv6")] From 972cdd4265b24efb101c6b9df373466fcbccac5d Mon Sep 17 00:00:00 2001 From: pennae Date: Wed, 5 Jul 2023 20:05:34 +0200 Subject: [PATCH 059/148] rp/adc: rewrite the module - don't require an irq binding for blocking-only adc - abstract adc pins into an AnyPin like interface, erasing the actual peripheral type at runtime. - add pull-up/pull-down functions for adc pins - add a test (mostly a copy of the example, to be honest) - configure adc pads according to datasheet - report conversion errors (although they seem exceedingly rare?) - drop embedded-hal interfaces. embedded-hal channels can do neither AnyPin nor pullup/pulldown without encoding both into the type --- embassy-rp/src/adc.rs | 227 +++++++++++++++++++++++-------------- embassy-rp/src/gpio.rs | 2 +- examples/rp/src/bin/adc.rs | 17 +-- tests/rp/src/bin/adc.rs | 86 ++++++++++++++ 4 files changed, 238 insertions(+), 94 deletions(-) create mode 100644 tests/rp/src/bin/adc.rs diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs index 699a0d61..dfa1b877 100644 --- a/embassy-rp/src/adc.rs +++ b/embassy-rp/src/adc.rs @@ -3,22 +3,17 @@ use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; +use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; -use embedded_hal_02::adc::{Channel, OneShot}; -use crate::gpio::Pin; +use crate::gpio::sealed::Pin as GpioPin; +use crate::gpio::{self, AnyPin, Pull}; use crate::interrupt::typelevel::Binding; use crate::interrupt::InterruptExt; use crate::peripherals::ADC; use crate::{interrupt, pac, peripherals, Peripheral}; -static WAKER: AtomicWaker = AtomicWaker::new(); -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[non_exhaustive] -pub enum Error { - // No errors for now -} +static WAKER: AtomicWaker = AtomicWaker::new(); #[non_exhaustive] pub struct Config {} @@ -28,11 +23,65 @@ impl Default for Config { Self {} } } -pub struct Adc<'d> { - phantom: PhantomData<&'d ADC>, + +pub struct Pin<'p> { + pin: PeripheralRef<'p, AnyPin>, } -impl<'d> Adc<'d> { +impl<'p> Pin<'p> { + pub fn new(pin: impl Peripheral

+ 'p, pull: Pull) -> Self { + into_ref!(pin); + pin.pad_ctrl().modify(|w| { + // manual says: + // + // > When using an ADC input shared with a GPIO pin, the pin’s + // > digital functions must be disabled by setting IE low and OD + // > high in the pin’s pad control register + w.set_ie(false); + w.set_od(true); + w.set_pue(pull == Pull::Up); + w.set_pde(pull == Pull::Down); + }); + Self { pin: pin.map_into() } + } + + fn channel(&self) -> u8 { + // this requires adc pins to be sequential and matching the adc channels, + // which is the case for rp2040 + self.pin._pin() - 26 + } +} + +impl<'d> Drop for Pin<'d> { + fn drop(&mut self) { + self.pin.pad_ctrl().modify(|w| { + w.set_ie(true); + w.set_od(false); + w.set_pue(false); + w.set_pde(true); + }); + } +} + +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Error { + ConversionFailed, +} + +pub trait Mode {} + +pub struct Async; +impl Mode for Async {} + +pub struct Blocking; +impl Mode for Blocking {} + +pub struct Adc<'d, M: Mode> { + phantom: PhantomData<(&'d ADC, M)>, +} + +impl<'d, M: Mode> Adc<'d, M> { #[inline] fn regs() -> pac::adc::Adc { pac::ADC @@ -45,11 +94,7 @@ impl<'d> Adc<'d> { ret } - pub fn new( - _inner: impl Peripheral

+ 'd, - _irq: impl Binding, - _config: Config, - ) -> Self { + fn setup() { let reset = Self::reset(); crate::reset::reset(reset); crate::reset::unreset_wait(reset); @@ -58,6 +103,43 @@ impl<'d> Adc<'d> { r.cs().write(|w| w.set_en(true)); // Wait for ADC ready while !r.cs().read().ready() {} + } + + fn sample_blocking(channel: u8) -> Result { + let r = Self::regs(); + r.cs().modify(|w| { + w.set_ainsel(channel); + w.set_start_once(true); + w.set_err(true); + }); + while !r.cs().read().ready() {} + match r.cs().read().err() { + true => Err(Error::ConversionFailed), + false => Ok(r.result().read().result().into()), + } + } + + pub fn blocking_read(&mut self, pin: &mut Pin) -> Result { + Self::sample_blocking(pin.channel()) + } + + pub fn blocking_read_temperature(&mut self) -> Result { + let r = Self::regs(); + r.cs().modify(|w| w.set_ts_en(true)); + while !r.cs().read().ready() {} + let result = Self::sample_blocking(4); + r.cs().modify(|w| w.set_ts_en(false)); + result + } +} + +impl<'d> Adc<'d, Async> { + pub fn new( + _inner: impl Peripheral

+ 'd, + _irq: impl Binding, + _config: Config, + ) -> Self { + Self::setup(); // Setup IRQ interrupt::ADC_IRQ_FIFO.unpend(); @@ -80,76 +162,42 @@ impl<'d> Adc<'d> { .await; } - pub async fn read, ID = u8> + Pin>(&mut self, pin: &mut PIN) -> u16 { + async fn sample_async(channel: u8) -> Result { let r = Self::regs(); - // disable pull-down and pull-up resistors - // pull-down resistors are enabled by default - pin.pad_ctrl().modify(|w| { - w.set_ie(true); - let (pu, pd) = (false, false); - w.set_pue(pu); - w.set_pde(pd); - }); r.cs().modify(|w| { - w.set_ainsel(PIN::channel()); - w.set_start_once(true) + w.set_ainsel(channel); + w.set_start_once(true); + w.set_err(true); }); Self::wait_for_ready().await; - r.result().read().result().into() + match r.cs().read().err() { + true => Err(Error::ConversionFailed), + false => Ok(r.result().read().result().into()), + } } - pub async fn read_temperature(&mut self) -> u16 { + pub async fn read(&mut self, pin: &mut Pin<'_>) -> Result { + Self::sample_async(pin.channel()).await + } + + pub async fn read_temperature(&mut self) -> Result { let r = Self::regs(); r.cs().modify(|w| w.set_ts_en(true)); if !r.cs().read().ready() { Self::wait_for_ready().await; } - r.cs().modify(|w| { - w.set_ainsel(4); - w.set_start_once(true) - }); - Self::wait_for_ready().await; - r.result().read().result().into() - } - - pub fn blocking_read, ID = u8> + Pin>(&mut self, pin: &mut PIN) -> u16 { - let r = Self::regs(); - pin.pad_ctrl().modify(|w| { - w.set_ie(true); - let (pu, pd) = (false, false); - w.set_pue(pu); - w.set_pde(pd); - }); - r.cs().modify(|w| { - w.set_ainsel(PIN::channel()); - w.set_start_once(true) - }); - while !r.cs().read().ready() {} - r.result().read().result().into() - } - - pub fn blocking_read_temperature(&mut self) -> u16 { - let r = Self::regs(); - r.cs().modify(|w| w.set_ts_en(true)); - while !r.cs().read().ready() {} - r.cs().modify(|w| { - w.set_ainsel(4); - w.set_start_once(true) - }); - while !r.cs().read().ready() {} - r.result().read().result().into() + let result = Self::sample_async(4).await; + r.cs().modify(|w| w.set_ts_en(false)); + result } } -macro_rules! impl_pin { - ($pin:ident, $channel:expr) => { - impl Channel> for peripherals::$pin { - type ID = u8; - fn channel() -> u8 { - $channel - } - } - }; +impl<'d> Adc<'d, Blocking> { + pub fn new_blocking(_inner: impl Peripheral

+ 'd, _config: Config) -> Self { + Self::setup(); + + Self { phantom: PhantomData } + } } pub struct InterruptHandler { @@ -158,24 +206,33 @@ pub struct InterruptHandler { impl interrupt::typelevel::Handler for InterruptHandler { unsafe fn on_interrupt() { - let r = Adc::regs(); + let r = Adc::::regs(); r.inte().write(|w| w.set_fifo(false)); WAKER.wake(); } } +mod sealed { + pub trait AdcPin: crate::gpio::sealed::Pin { + fn channel(&mut self) -> u8; + } +} + +pub trait AdcPin: sealed::AdcPin + gpio::Pin {} + +macro_rules! impl_pin { + ($pin:ident, $channel:expr) => { + impl sealed::AdcPin for peripherals::$pin { + fn channel(&mut self) -> u8 { + $channel + } + } + + impl AdcPin for peripherals::$pin {} + }; +} + impl_pin!(PIN_26, 0); impl_pin!(PIN_27, 1); impl_pin!(PIN_28, 2); impl_pin!(PIN_29, 3); - -impl OneShot, WORD, PIN> for Adc<'static> -where - WORD: From, - PIN: Channel, ID = u8> + Pin, -{ - type Error = (); - fn read(&mut self, pin: &mut PIN) -> nb::Result { - Ok(self.blocking_read(pin).into()) - } -} diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index f8048a4d..d18fb909 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -41,7 +41,7 @@ impl From for bool { } /// Represents a pull setting for an input. -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum Pull { None, Up, diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 7c2ca19f..65069cde 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs @@ -4,8 +4,9 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::adc::{Adc, Config, InterruptHandler}; +use embassy_rp::adc::{Adc, Config, InterruptHandler, Pin}; use embassy_rp::bind_interrupts; +use embassy_rp::gpio::Pull; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -18,18 +19,18 @@ async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); let mut adc = Adc::new(p.ADC, Irqs, Config::default()); - let mut p26 = p.PIN_26; - let mut p27 = p.PIN_27; - let mut p28 = p.PIN_28; + let mut p26 = Pin::new(p.PIN_26, Pull::None); + let mut p27 = Pin::new(p.PIN_27, Pull::None); + let mut p28 = Pin::new(p.PIN_28, Pull::None); loop { - let level = adc.read(&mut p26).await; + let level = adc.read(&mut p26).await.unwrap(); info!("Pin 26 ADC: {}", level); - let level = adc.read(&mut p27).await; + let level = adc.read(&mut p27).await.unwrap(); info!("Pin 27 ADC: {}", level); - let level = adc.read(&mut p28).await; + let level = adc.read(&mut p28).await.unwrap(); info!("Pin 28 ADC: {}", level); - let temp = adc.read_temperature().await; + let temp = adc.read_temperature().await.unwrap(); info!("Temp: {} degrees", convert_to_celsius(temp)); Timer::after(Duration::from_secs(1)).await; } diff --git a/tests/rp/src/bin/adc.rs b/tests/rp/src/bin/adc.rs new file mode 100644 index 00000000..e659844a --- /dev/null +++ b/tests/rp/src/bin/adc.rs @@ -0,0 +1,86 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +#[path = "../common.rs"] +mod common; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::adc::{Adc, Config, InterruptHandler, Pin}; +use embassy_rp::bind_interrupts; +use embassy_rp::gpio::Pull; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + ADC_IRQ_FIFO => InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut p = embassy_rp::init(Default::default()); + let mut adc = Adc::new(p.ADC, Irqs, Config::default()); + + { + { + let mut p = Pin::new(&mut p.PIN_26, Pull::Down); + defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); + defmt::assert!(adc.read(&mut p).await.unwrap() < 0b01_0000_0000); + } + { + let mut p = Pin::new(&mut p.PIN_26, Pull::Up); + defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); + defmt::assert!(adc.read(&mut p).await.unwrap() > 0b11_0000_0000); + } + } + // not bothering with async reads from now on + { + { + let mut p = Pin::new(&mut p.PIN_27, Pull::Down); + defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); + } + { + let mut p = Pin::new(&mut p.PIN_27, Pull::Up); + defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); + } + } + { + { + let mut p = Pin::new(&mut p.PIN_28, Pull::Down); + defmt::assert!(adc.blocking_read(&mut p).unwrap() < 0b01_0000_0000); + } + { + let mut p = Pin::new(&mut p.PIN_28, Pull::Up); + defmt::assert!(adc.blocking_read(&mut p).unwrap() > 0b11_0000_0000); + } + } + { + // gp29 is connected to vsys through a 200k/100k divider, + // adding pulls should change the value + let low = { + let mut p = Pin::new(&mut p.PIN_29, Pull::Down); + adc.blocking_read(&mut p).unwrap() + }; + let none = { + let mut p = Pin::new(&mut p.PIN_29, Pull::None); + adc.blocking_read(&mut p).unwrap() + }; + let up = { + let mut p = Pin::new(&mut p.PIN_29, Pull::Up); + adc.blocking_read(&mut p).unwrap() + }; + defmt::assert!(low < none); + defmt::assert!(none < up); + } + + let temp = convert_to_celsius(adc.read_temperature().await.unwrap()); + defmt::assert!(temp > 0.0); + defmt::assert!(temp < 60.0); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} + +fn convert_to_celsius(raw_temp: u16) -> f32 { + // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet + 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721 as f32 +} From 69b4e898b3ac9e21deef56cb1dde34aa860e3f00 Mon Sep 17 00:00:00 2001 From: David Purser <60577982+davidpurser@users.noreply.github.com> Date: Fri, 7 Jul 2023 20:52:44 -0500 Subject: [PATCH 060/148] Correctly calculate target VCO frequency from multipliers --- embassy-stm32/src/rcc/h7.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs index f3a98c79..7e5cd0d1 100644 --- a/embassy-stm32/src/rcc/h7.rs +++ b/embassy-stm32/src/rcc/h7.rs @@ -740,7 +740,7 @@ mod pll { } }; - let vco_ck = output + pll_x_p; + let vco_ck = output * pll_x_p; assert!(pll_x_p < 128); assert!(vco_ck >= VCO_MIN); From 05c524a7db1ee1ecc5397570a5dd00faf4b7316a Mon Sep 17 00:00:00 2001 From: James Waples Date: Sat, 8 Jul 2023 11:20:26 +0100 Subject: [PATCH 061/148] Enable `critical-section/std` when using `std` feature of `embassy-time` --- embassy-time/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml index 0ff0e3be..0afb1103 100644 --- a/embassy-time/Cargo.toml +++ b/embassy-time/Cargo.toml @@ -23,7 +23,7 @@ target = "x86_64-unknown-linux-gnu" features = ["nightly", "defmt", "unstable-traits", "std"] [features] -std = ["tick-hz-1_000_000"] +std = ["tick-hz-1_000_000", "critical-section/std"] wasm = ["dep:wasm-bindgen", "dep:js-sys", "dep:wasm-timer", "tick-hz-1_000_000"] # Enable nightly-only features From 735d676a725999eda3869e7323c6264c2e8c2cb9 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 9 Jul 2023 15:50:01 -0500 Subject: [PATCH 062/148] wpan: update alignment control --- embassy-stm32-wpan/src/cmd.rs | 2 +- embassy-stm32-wpan/src/consts.rs | 1 + embassy-stm32-wpan/src/lib.rs | 40 ++++++++----- embassy-stm32-wpan/src/sub/mm.rs | 12 ++-- embassy-stm32-wpan/src/tables.rs | 96 ++++++++++++++++++-------------- 5 files changed, 90 insertions(+), 61 deletions(-) diff --git a/embassy-stm32-wpan/src/cmd.rs b/embassy-stm32-wpan/src/cmd.rs index 8428b6ff..92835738 100644 --- a/embassy-stm32-wpan/src/cmd.rs +++ b/embassy-stm32-wpan/src/cmd.rs @@ -37,7 +37,7 @@ pub struct CmdSerialStub { } #[derive(Copy, Clone, Default)] -#[repr(C, packed(4))] +#[repr(C, packed)] pub struct CmdPacket { pub header: PacketHeader, pub cmdserial: CmdSerial, diff --git a/embassy-stm32-wpan/src/consts.rs b/embassy-stm32-wpan/src/consts.rs index f234151d..1c84addb 100644 --- a/embassy-stm32-wpan/src/consts.rs +++ b/embassy-stm32-wpan/src/consts.rs @@ -79,6 +79,7 @@ pub const CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255; pub const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE; pub const POOL_SIZE: usize = CFG_TL_BLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); +pub const C_SIZE_CMD_STRING: usize = 256; pub const fn divc(x: usize, y: usize) -> usize { (x + y - 1) / y diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index 99c61058..3a45c597 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -60,9 +60,9 @@ impl<'d> TlMbox<'d> { mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), traces_table: TL_TRACES_TABLE.as_ptr(), mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), - // zigbee_table: TL_ZIGBEE_TABLE.as_ptr(), - // lld_tests_table: TL_LLD_TESTS_TABLE.as_ptr(), - // ble_lld_table: TL_BLE_LLD_TABLE.as_ptr(), + zigbee_table: TL_ZIGBEE_TABLE.as_ptr(), + lld_tests_table: TL_LLD_TESTS_TABLE.as_ptr(), + ble_lld_table: TL_BLE_LLD_TABLE.as_ptr(), }); TL_SYS_TABLE @@ -87,15 +87,15 @@ impl<'d> TlMbox<'d> { TL_MAC_802_15_4_TABLE .as_mut_ptr() .write_volatile(MaybeUninit::zeroed().assume_init()); - // TL_ZIGBEE_TABLE - // .as_mut_ptr() - // .write_volatile(MaybeUninit::zeroed().assume_init()); - // TL_LLD_TESTS_TABLE - // .as_mut_ptr() - // .write_volatile(MaybeUninit::zeroed().assume_init()); - // TL_BLE_LLD_TABLE - // .as_mut_ptr() - // .write_volatile(MaybeUninit::zeroed().assume_init()); + TL_ZIGBEE_TABLE + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + TL_LLD_TESTS_TABLE + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + TL_BLE_LLD_TABLE + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); EVT_POOL .as_mut_ptr() @@ -103,18 +103,30 @@ impl<'d> TlMbox<'d> { SYS_SPARE_EVT_BUF .as_mut_ptr() .write_volatile(MaybeUninit::zeroed().assume_init()); - BLE_SPARE_EVT_BUF + CS_BUFFER .as_mut_ptr() .write_volatile(MaybeUninit::zeroed().assume_init()); + #[cfg(feature = "ble")] { + BLE_SPARE_EVT_BUF + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + BLE_CMD_BUFFER .as_mut_ptr() .write_volatile(MaybeUninit::zeroed().assume_init()); HCI_ACL_DATA_BUFFER .as_mut_ptr() .write_volatile(MaybeUninit::zeroed().assume_init()); - CS_BUFFER + } + + #[cfg(feature = "mac")] + { + MAC_802_15_4_CMD_BUFFER + .as_mut_ptr() + .write_volatile(MaybeUninit::zeroed().assume_init()); + MAC_802_15_4_NOTIF_RSP_EVT_BUFFER .as_mut_ptr() .write_volatile(MaybeUninit::zeroed().assume_init()); } diff --git a/embassy-stm32-wpan/src/sub/mm.rs b/embassy-stm32-wpan/src/sub/mm.rs index 1f2ecac2..da05ad1d 100644 --- a/embassy-stm32-wpan/src/sub/mm.rs +++ b/embassy-stm32-wpan/src/sub/mm.rs @@ -4,20 +4,21 @@ use core::marker::PhantomData; use core::mem::MaybeUninit; use core::task::Poll; +use aligned::{Aligned, A4}; use cortex_m::interrupt; use embassy_stm32::ipcc::Ipcc; use embassy_sync::waitqueue::AtomicWaker; use crate::consts::POOL_SIZE; use crate::evt::EvtPacket; -use crate::tables::{ - MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, -}; +#[cfg(feature = "ble")] +use crate::tables::BLE_SPARE_EVT_BUF; +use crate::tables::{MemManagerTable, EVT_POOL, FREE_BUF_QUEUE, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE}; use crate::unsafe_linked_list::LinkedListNode; use crate::{channels, evt}; static MM_WAKER: AtomicWaker = AtomicWaker::new(); -static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit = MaybeUninit::uninit(); +static mut LOCAL_FREE_BUF_QUEUE: Aligned> = Aligned(MaybeUninit::uninit()); pub struct MemoryManager { phantom: PhantomData, @@ -30,7 +31,10 @@ impl MemoryManager { LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); TL_MEM_MANAGER_TABLE.as_mut_ptr().write_volatile(MemManagerTable { + #[cfg(feature = "ble")] spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), + #[cfg(not(feature = "ble"))] + spare_ble_buffer: core::ptr::null(), spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), blepool: EVT_POOL.as_ptr().cast(), blepoolsize: POOL_SIZE as u32, diff --git a/embassy-stm32-wpan/src/tables.rs b/embassy-stm32-wpan/src/tables.rs index 1b5dcdf2..f2c25052 100644 --- a/embassy-stm32-wpan/src/tables.rs +++ b/embassy-stm32-wpan/src/tables.rs @@ -4,6 +4,8 @@ use aligned::{Aligned, A4}; use bit_field::BitField; use crate::cmd::{AclDataPacket, CmdPacket}; +#[cfg(feature = "mac")] +use crate::consts::C_SIZE_CMD_STRING; use crate::consts::{POOL_SIZE, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE}; use crate::unsafe_linked_list::LinkedListNode; @@ -80,7 +82,7 @@ impl WirelessFwInfoTable { } #[derive(Debug, Clone)] -#[repr(C, align(4))] +#[repr(C)] pub struct DeviceInfoTable { pub safe_boot_info_table: SafeBootInfoTable, pub rss_info_table: RssInfoTable, @@ -88,7 +90,7 @@ pub struct DeviceInfoTable { } #[derive(Debug)] -#[repr(C, align(4))] +#[repr(C)] pub struct BleTable { pub pcmd_buffer: *mut CmdPacket, pub pcs_buffer: *const u8, @@ -97,16 +99,15 @@ pub struct BleTable { } #[derive(Debug)] -#[repr(C, align(4))] +#[repr(C)] pub struct ThreadTable { pub nostack_buffer: *const u8, pub clicmdrsp_buffer: *const u8, pub otcmdrsp_buffer: *const u8, } -// TODO: use later #[derive(Debug)] -#[repr(C, align(4))] +#[repr(C)] pub struct LldTestsTable { pub clicmdrsp_buffer: *const u8, pub m0cmd_buffer: *const u8, @@ -114,7 +115,7 @@ pub struct LldTestsTable { // TODO: use later #[derive(Debug)] -#[repr(C, align(4))] +#[repr(C)] pub struct BleLldTable { pub cmdrsp_buffer: *const u8, pub m0cmd_buffer: *const u8, @@ -122,7 +123,7 @@ pub struct BleLldTable { // TODO: use later #[derive(Debug)] -#[repr(C, align(4))] +#[repr(C)] pub struct ZigbeeTable { pub notif_m0_to_m4_buffer: *const u8, pub appli_cmd_m4_to_m0_bufer: *const u8, @@ -130,14 +131,14 @@ pub struct ZigbeeTable { } #[derive(Debug)] -#[repr(C, align(4))] +#[repr(C)] pub struct SysTable { pub pcmd_buffer: *mut CmdPacket, pub sys_queue: *const LinkedListNode, } #[derive(Debug)] -#[repr(C, align(4))] +#[repr(C)] pub struct MemManagerTable { pub spare_ble_buffer: *const u8, pub spare_sys_buffer: *const u8, @@ -152,13 +153,13 @@ pub struct MemManagerTable { } #[derive(Debug)] -#[repr(C, align(4))] +#[repr(C)] pub struct TracesTable { pub traces_queue: *const u8, } #[derive(Debug)] -#[repr(C, align(4))] +#[repr(C)] pub struct Mac802_15_4Table { pub p_cmdrsp_buffer: *const u8, pub p_notack_buffer: *const u8, @@ -176,6 +177,9 @@ pub struct RefTable { pub mem_manager_table: *const MemManagerTable, pub traces_table: *const TracesTable, pub mac_802_15_4_table: *const Mac802_15_4Table, + pub zigbee_table: *const ZigbeeTable, + pub lld_tests_table: *const LldTestsTable, + pub ble_lld_table: *const BleLldTable, } // --------------------- ref table --------------------- @@ -183,57 +187,57 @@ pub struct RefTable { pub static mut TL_REF_TABLE: MaybeUninit = MaybeUninit::uninit(); #[link_section = "MB_MEM1"] -pub static mut TL_DEVICE_INFO_TABLE: MaybeUninit = MaybeUninit::uninit(); +pub static mut TL_DEVICE_INFO_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); #[link_section = "MB_MEM1"] -pub static mut TL_BLE_TABLE: MaybeUninit = MaybeUninit::uninit(); +pub static mut TL_BLE_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); #[link_section = "MB_MEM1"] -pub static mut TL_THREAD_TABLE: MaybeUninit = MaybeUninit::uninit(); - -// #[link_section = "MB_MEM1"] -// pub static mut TL_LLD_TESTS_TABLE: MaybeUninit = MaybeUninit::uninit(); - -// #[link_section = "MB_MEM1"] -// pub static mut TL_BLE_LLD_TABLE: MaybeUninit = MaybeUninit::uninit(); +pub static mut TL_THREAD_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); #[link_section = "MB_MEM1"] -pub static mut TL_SYS_TABLE: MaybeUninit = MaybeUninit::uninit(); +pub static mut TL_LLD_TESTS_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); #[link_section = "MB_MEM1"] -pub static mut TL_MEM_MANAGER_TABLE: MaybeUninit = MaybeUninit::uninit(); +pub static mut TL_BLE_LLD_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); #[link_section = "MB_MEM1"] -pub static mut TL_TRACES_TABLE: MaybeUninit = MaybeUninit::uninit(); +pub static mut TL_SYS_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); #[link_section = "MB_MEM1"] -pub static mut TL_MAC_802_15_4_TABLE: MaybeUninit = MaybeUninit::uninit(); +pub static mut TL_MEM_MANAGER_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); -// #[link_section = "MB_MEM1"] -// pub static mut TL_ZIGBEE_TABLE: MaybeUninit = MaybeUninit::uninit(); +#[link_section = "MB_MEM1"] +pub static mut TL_TRACES_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); + +#[link_section = "MB_MEM1"] +pub static mut TL_MAC_802_15_4_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); + +#[link_section = "MB_MEM1"] +pub static mut TL_ZIGBEE_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); // --------------------- tables --------------------- #[link_section = "MB_MEM1"] -pub static mut FREE_BUF_QUEUE: MaybeUninit = MaybeUninit::uninit(); +pub static mut FREE_BUF_QUEUE: Aligned> = Aligned(MaybeUninit::uninit()); #[allow(dead_code)] #[link_section = "MB_MEM1"] -pub static mut TRACES_EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); +pub static mut TRACES_EVT_QUEUE: Aligned> = Aligned(MaybeUninit::uninit()); #[link_section = "MB_MEM2"] -pub static mut CS_BUFFER: MaybeUninit> = - MaybeUninit::uninit(); +pub static mut CS_BUFFER: Aligned> = + Aligned(MaybeUninit::uninit()); #[link_section = "MB_MEM2"] -pub static mut EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); +pub static mut EVT_QUEUE: Aligned> = Aligned(MaybeUninit::uninit()); #[link_section = "MB_MEM2"] -pub static mut SYSTEM_EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); +pub static mut SYSTEM_EVT_QUEUE: Aligned> = Aligned(MaybeUninit::uninit()); // --------------------- app tables --------------------- #[cfg(feature = "mac")] #[link_section = "MB_MEM2"] -pub static mut MAC_802_15_4_CMD_BUFFER: MaybeUninit = MaybeUninit::uninit(); +pub static mut MAC_802_15_4_CMD_BUFFER: Aligned> = Aligned(MaybeUninit::uninit()); #[cfg(feature = "mac")] #[link_section = "MB_MEM2"] @@ -242,23 +246,31 @@ pub static mut MAC_802_15_4_NOTIF_RSP_EVT_BUFFER: MaybeUninit< > = MaybeUninit::uninit(); #[link_section = "MB_MEM2"] -pub static mut EVT_POOL: MaybeUninit> = MaybeUninit::uninit(); +pub static mut EVT_POOL: Aligned> = Aligned(MaybeUninit::uninit()); #[link_section = "MB_MEM2"] -pub static mut SYS_CMD_BUF: MaybeUninit = MaybeUninit::uninit(); +pub static mut SYS_CMD_BUF: Aligned> = Aligned(MaybeUninit::uninit()); #[link_section = "MB_MEM2"] -pub static mut SYS_SPARE_EVT_BUF: MaybeUninit> = - MaybeUninit::uninit(); +pub static mut SYS_SPARE_EVT_BUF: Aligned> = + Aligned(MaybeUninit::uninit()); +#[cfg(feature = "mac")] +#[link_section = "MB_MEM2"] +pub static mut MAC_802_15_4_CNFINDNOT: Aligned> = + Aligned(MaybeUninit::uninit()); + +#[cfg(feature = "ble")] #[link_section = "MB_MEM1"] -pub static mut BLE_CMD_BUFFER: MaybeUninit = MaybeUninit::uninit(); +pub static mut BLE_CMD_BUFFER: Aligned> = Aligned(MaybeUninit::uninit()); +#[cfg(feature = "ble")] #[link_section = "MB_MEM2"] -pub static mut BLE_SPARE_EVT_BUF: MaybeUninit> = - MaybeUninit::uninit(); +pub static mut BLE_SPARE_EVT_BUF: Aligned> = + Aligned(MaybeUninit::uninit()); +#[cfg(feature = "ble")] #[link_section = "MB_MEM2"] // fuck these "magic" numbers from ST ---v---v -pub static mut HCI_ACL_DATA_BUFFER: MaybeUninit> = - MaybeUninit::uninit(); +pub static mut HCI_ACL_DATA_BUFFER: Aligned> = + Aligned(MaybeUninit::uninit()); From c1bf5aee247060a0251fe13eefcb3c7369f44eb9 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 9 Jul 2023 16:01:13 -0500 Subject: [PATCH 063/148] mac: move table initialization after sys ready --- embassy-stm32-wpan/src/sub/mac.rs | 8 -------- embassy-stm32-wpan/src/sub/sys.rs | 19 +++++++++++++++++++ examples/stm32wb/src/bin/tl_mbox_mac.rs | 12 +++++++++++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs index fd8af860..62612dbf 100644 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ b/embassy-stm32-wpan/src/sub/mac.rs @@ -25,14 +25,6 @@ pub struct Mac { impl Mac { pub(crate) fn new() -> Self { - unsafe { - TL_MAC_802_15_4_TABLE.as_mut_ptr().write_volatile(Mac802_15_4Table { - p_cmdrsp_buffer: MAC_802_15_4_CMD_BUFFER.as_mut_ptr().cast(), - p_notack_buffer: MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr().cast(), - evt_queue: ptr::null_mut(), - }); - } - Self { phantom: PhantomData } } diff --git a/embassy-stm32-wpan/src/sub/sys.rs b/embassy-stm32-wpan/src/sub/sys.rs index af652860..caa4845f 100644 --- a/embassy-stm32-wpan/src/sub/sys.rs +++ b/embassy-stm32-wpan/src/sub/sys.rs @@ -65,6 +65,25 @@ impl Sys { #[cfg(feature = "mac")] pub async fn shci_c2_mac_802_15_4_init(&self) -> SchiCommandStatus { + use crate::tables::{ + Mac802_15_4Table, TracesTable, MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, + TL_MAC_802_15_4_TABLE, TL_TRACES_TABLE, TRACES_EVT_QUEUE, + }; + + unsafe { + LinkedListNode::init_head(TRACES_EVT_QUEUE.as_mut_ptr() as *mut _); + + TL_TRACES_TABLE.as_mut_ptr().write_volatile(TracesTable { + traces_queue: TRACES_EVT_QUEUE.as_ptr() as *const _, + }); + + TL_MAC_802_15_4_TABLE.as_mut_ptr().write_volatile(Mac802_15_4Table { + p_cmdrsp_buffer: MAC_802_15_4_CMD_BUFFER.as_mut_ptr().cast(), + p_notack_buffer: MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr().cast(), + evt_queue: core::ptr::null_mut(), + }); + }; + self.write_and_get_response(ShciOpcode::Mac802_15_4Init, &[]).await } diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs index f67be468..5931c392 100644 --- a/examples/stm32wb/src/bin/tl_mbox_mac.rs +++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs @@ -6,6 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -14,8 +15,13 @@ bind_interrupts!(struct Irqs{ IPCC_C1_TX => TransmitInterruptHandler; }); +#[embassy_executor::task] +async fn run_mm_queue(memory_manager: mm::MemoryManager) { + memory_manager.run_queue().await; +} + #[embassy_executor::main] -async fn main(_spawner: Spawner) { +async fn main(spawner: Spawner) { /* How to make this work: @@ -46,9 +52,13 @@ async fn main(_spawner: Spawner) { let config = Config::default(); let mbox = TlMbox::init(p.IPCC, Irqs, config); + spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); + core::mem::drop(sys_event); + let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; info!("initialized mac: {}", result); From bf4493dbdfe6f1d71e10af08b2094576c8fa7499 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 9 Jul 2023 16:08:39 -0500 Subject: [PATCH 064/148] rustfmt --- embassy-stm32-wpan/src/sub/mac.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs index 62612dbf..f7a59b0e 100644 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ b/embassy-stm32-wpan/src/sub/mac.rs @@ -11,9 +11,7 @@ use embassy_sync::waitqueue::AtomicWaker; use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::{EvtBox, EvtPacket}; -use crate::tables::{ - Mac802_15_4Table, MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, TL_MAC_802_15_4_TABLE, -}; +use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; use crate::{channels, evt}; static MAC_WAKER: AtomicWaker = AtomicWaker::new(); From 4aca7c8811b70e420280893784cdad2acbe326f9 Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 10 Jul 2023 16:54:48 +0100 Subject: [PATCH 065/148] wip --- embassy-stm32-wpan/Cargo.toml | 1 + embassy-stm32-wpan/src/sub/mac/commands.rs | 83 +++++++++++++ .../src/sub/{mac.rs => mac/mod.rs} | 18 +++ embassy-stm32-wpan/src/sub/mac/opcodes.rs | 27 ++++ examples/stm32wb/.cargo/config.toml | 4 +- examples/stm32wb/Cargo.toml | 6 +- examples/stm32wb/src/bin/tl_mbox_mac_2.rs | 117 ++++++++++++++++++ rust-toolchain.toml | 4 +- 8 files changed, 255 insertions(+), 5 deletions(-) create mode 100644 embassy-stm32-wpan/src/sub/mac/commands.rs rename embassy-stm32-wpan/src/sub/{mac.rs => mac/mod.rs} (88%) create mode 100644 embassy-stm32-wpan/src/sub/mac/opcodes.rs create mode 100644 examples/stm32wb/src/bin/tl_mbox_mac_2.rs diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 5141f9bd..4b5dcdd2 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -28,6 +28,7 @@ stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } stm32wb-hci = { version = "0.1.2", features = ["version-5-0"], optional = true } [features] +default = ["stm32wb55rg", "mac", "ble"] defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] ble = ["dep:stm32wb-hci"] diff --git a/embassy-stm32-wpan/src/sub/mac/commands.rs b/embassy-stm32-wpan/src/sub/mac/commands.rs new file mode 100644 index 00000000..75a31d2f --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/commands.rs @@ -0,0 +1,83 @@ +use bit_field::BitField; + +use super::opcodes::OpcodeM4ToM0; + +pub trait MacCommand { + type Response; + const OPCODE: OpcodeM4ToM0; + const SIZE: usize; + + fn copy_into_slice(&self, buf: &mut [u8]); +} + +pub struct ResetRequest { + /// MAC PIB attributes are set to their default values or not during reset + pub set_default_pib: bool, +} + +impl MacCommand for ResetRequest { + type Response = (); + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeResetReq; + const SIZE: usize = 4; + + fn copy_into_slice(&self, buf: &mut [u8]) { + buf[0] = self.set_default_pib as u8; + } +} + +#[repr(C)] +pub struct SetRequest { + pub pib_attribute_ptr: *const u8, + pub pib_attribute: u8, + pub stuffing: [u8; 3], +} + +impl MacCommand for SetRequest { + type Response = (); + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSetReq; + const SIZE: usize = 8; + + fn copy_into_slice(&self, buf: &mut [u8]) { + let address = self.pib_attribute_ptr as usize; + + // 68 ff 2 20 6f + + let a = unsafe { core::slice::from_raw_parts(&self as *const _ as *const u8, Self::SIZE) }; + debug!("{:#04x}", a); + + unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, 8) }; + + // buf[0] = self.pib_attribute_ptr as u8; + // buf[1] = self.pib_attribute; + } +} + +pub struct AssociateRequest { + pub channel_number: u8, + pub channel_page: u8, + pub coord_addr_mode: u8, + pub capability_information: u8, + pub coord_pan_id: [u8; 2], + pub security_level: u8, + pub key_id_mode: u8, + pub key_source: [u8; 8], + pub coord_address: MacAddress, + pub key_index: u8, +} + +impl MacCommand for AssociateRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateReq; + const SIZE: usize = 25; + type Response = (); + + fn copy_into_slice(&self, buf: &mut [u8]) { + let a = unsafe { core::slice::from_raw_parts(&self as *const _ as *const u8, core::mem::size_of::()) }; + + buf[..a.len()].copy_from_slice(a); + } +} + +pub union MacAddress { + pub short: [u8; 2], + pub extended: [u8; 8], +} diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs similarity index 88% rename from embassy-stm32-wpan/src/sub/mac.rs rename to embassy-stm32-wpan/src/sub/mac/mod.rs index f7a59b0e..83970a88 100644 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -8,12 +8,16 @@ use embassy_futures::poll_once; use embassy_stm32::ipcc::Ipcc; use embassy_sync::waitqueue::AtomicWaker; +use self::commands::MacCommand; use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::{EvtBox, EvtPacket}; use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; use crate::{channels, evt}; +pub mod commands; +mod opcodes; + static MAC_WAKER: AtomicWaker = AtomicWaker::new(); static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false); @@ -77,8 +81,22 @@ impl Mac { }) .await; } + + pub async fn send_command(&self, cmd: T) -> u8 + where + T: MacCommand, + { + let mut payload = [0u8; MAX_PACKET_SIZE]; + cmd.copy_into_slice(&mut payload); + + debug!("sending {:#x}", payload[..T::SIZE]); + + self.write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]).await + } } +const MAX_PACKET_SIZE: usize = 255; + impl evt::MemoryManager for Mac { /// SAFETY: passing a pointer to something other than a managed event packet is UB unsafe fn drop_event_packet(_: *mut EvtPacket) { diff --git a/embassy-stm32-wpan/src/sub/mac/opcodes.rs b/embassy-stm32-wpan/src/sub/mac/opcodes.rs new file mode 100644 index 00000000..511b7815 --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/opcodes.rs @@ -0,0 +1,27 @@ +const ST_VENDOR_OGF: u16 = 0x3F; +const MAC_802_15_4_CMD_OPCODE_OFFSET: u16 = 0x280; + +const fn opcode(ocf: u16) -> isize { + ((ST_VENDOR_OGF << 9) | (MAC_802_15_4_CMD_OPCODE_OFFSET + ocf)) as isize +} + +pub enum OpcodeM4ToM0 { + MlmeAssociateReq = opcode(0x00), + MlmeAssociateRes = opcode(0x01), + MlmeDisassociateReq = opcode(0x02), + MlmeGetReq = opcode(0x03), + MlmeGtsReq = opcode(0x04), + MlmeOrphanRes = opcode(0x05), + MlmeResetReq = opcode(0x06), + MlmeRxEnableReq = opcode(0x07), + MlmeScanReq = opcode(0x08), + MlmeSetReq = opcode(0x09), + MlmeStartReq = opcode(0x0A), + MlmeSyncReq = opcode(0x0B), + MlmePollReq = opcode(0x0C), + MlmeDpsReq = opcode(0x0D), + MlmeSoundingReq = opcode(0x0E), + MlmeCalibrateReq = opcode(0x0F), + McpsDataReq = opcode(0x10), + McpsPurgeReq = opcode(0x11), +} diff --git a/examples/stm32wb/.cargo/config.toml b/examples/stm32wb/.cargo/config.toml index 8b6d6d75..cf62a10a 100644 --- a/examples/stm32wb/.cargo/config.toml +++ b/examples/stm32wb/.cargo/config.toml @@ -1,7 +1,7 @@ [target.'cfg(all(target_arch = "arm", target_os = "none"))'] # replace STM32WB55CCUx with your chip as listed in `probe-rs chip list` -# runner = "probe-rs run --chip STM32WB55RGVx --speed 1000 --connect-under-reset" -runner = "teleprobe local run --chip STM32WB55RG --elf" +runner = "probe-run --chip STM32WB55RGVx --speed 1000 --connect-under-reset" +# runner = "teleprobe local run --chip STM32WB55RG --elf" [build] target = "thumbv7em-none-eabihf" diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 203ca148..10973454 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -23,7 +23,7 @@ heapless = { version = "0.7.5", default-features = false } [features] -default = ["ble"] +default = ["ble", "mac"] mac = ["embassy-stm32-wpan/mac"] ble = ["embassy-stm32-wpan/ble"] @@ -35,6 +35,10 @@ required-features = ["ble"] name = "tl_mbox_mac" required-features = ["mac"] +[[bin]] +name = "tl_mbox_mac_2" +required-features = ["mac"] + [[bin]] name = "eddystone_beacon" required-features = ["ble"] diff --git a/examples/stm32wb/src/bin/tl_mbox_mac_2.rs b/examples/stm32wb/src/bin/tl_mbox_mac_2.rs new file mode 100644 index 00000000..e069adf8 --- /dev/null +++ b/examples/stm32wb/src/bin/tl_mbox_mac_2.rs @@ -0,0 +1,117 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::bind_interrupts; +use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, MacAddress, ResetRequest, SetRequest}; +use embassy_stm32_wpan::sub::mm; +use embassy_stm32_wpan::TlMbox; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs{ + IPCC_C1_RX => ReceiveInterruptHandler; + IPCC_C1_TX => TransmitInterruptHandler; +}); + +#[embassy_executor::task] +async fn run_mm_queue(memory_manager: mm::MemoryManager) { + memory_manager.run_queue().await; +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + /* + How to make this work: + + - Obtain a NUCLEO-STM32WB55 from your preferred supplier. + - Download and Install STM32CubeProgrammer. + - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from + gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x + - Open STM32CubeProgrammer + - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. + - Once complete, click connect to connect to the device. + - On the left hand pane, click the RSS signal icon to open "Firmware Upgrade Services". + - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file + - Select that file, the memory address, "verify download", and then "Firmware Upgrade". + - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the + stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. + - Select that file, the memory address, "verify download", and then "Firmware Upgrade". + - Select "Start Wireless Stack". + - Disconnect from the device. + - In the examples folder for stm32wb, modify the memory.x file to match your target device. + - Run this example. + + Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. + */ + + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + + let config = Config::default(); + let mbox = TlMbox::init(p.IPCC, Irqs, config); + + spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + + let sys_event = mbox.sys_subsystem.read().await; + info!("sys event: {}", sys_event.payload()); + + core::mem::drop(sys_event); + + let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; + info!("initialized mac: {}", result); + + info!("resetting"); + let response = mbox + .mac_subsystem + .send_command(ResetRequest { set_default_pib: true }) + .await; + info!("{}", response); + + info!("setting extended address"); + let extended_address: u64 = 0xACDE480000000001; + defmt::debug!("{}", &extended_address as *const _ as *const u8); + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &extended_address as *const _ as *const u8, + pib_attribute: 0x6F, + stuffing: [0; 3], + }) + .await; + info!("{}", response); + + // info!("association request"); + // mbox.mac_subsystem + // .send_command(AssociateRequest { + // channel_number: 16, + // channel_page: 0, + // coord_addr_mode: 2, + // coord_address: MacAddress { short: [0x22, 0x11] }, + // capability_information: 0x80, + // coord_pan_id: [0xAA, 0x1A], + // security_level: 0, + + // key_id_mode: 0, + // key_index: 0, + // key_source: [0; 8], + // }) + // .await; + // info!("reading"); + // let result = mbox.mac_subsystem.read().await; + // info!("{}", result.payload()); + + // + // info!("starting ble..."); + // mbox.ble_subsystem.t_write(0x0c, &[]).await; + // + // info!("waiting for ble..."); + // let ble_event = mbox.ble_subsystem.tl_read().await; + // + // info!("ble event: {}", ble_event.payload()); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 5db74c7a..bad6d3a4 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,8 +1,8 @@ # 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" -components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] +channel = "nightly" +components = [ "rust-src", "rustfmt", "llvm-tools" ] targets = [ "thumbv7em-none-eabi", "thumbv7m-none-eabi", From 29f3d5b68d3b5949de35227359bf631661613b14 Mon Sep 17 00:00:00 2001 From: shakencodes Date: Mon, 10 Jul 2023 16:40:18 -0700 Subject: [PATCH 066/148] Ensure I2C master_stop() called after error --- embassy-stm32/src/i2c/v2.rs | 52 +++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 1f036d55..208d1527 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -382,13 +382,18 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { // I2C start // // ST SAD+W - Self::master_write( + if let Err(err) = Self::master_write( address, write.len().min(255), Stop::Software, last_chunk_idx != 0, &check_timeout, - )?; + ) { + if send_stop { + self.master_stop(); + } + return Err(err); + } for (number, chunk) in write.chunks(255).enumerate() { if number != 0 { @@ -399,18 +404,22 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { // Wait until we are allowed to send data // (START has been ACKed or last byte when // through) - self.wait_txe(&check_timeout)?; + if let Err(err) = self.wait_txe(&check_timeout) { + if send_stop { + self.master_stop(); + } + return Err(err); + } T::regs().txdr().write(|w| w.set_txdata(*byte)); } } // Wait until the write finishes - self.wait_tc(&check_timeout)?; - + let result = self.wait_tc(&check_timeout); if send_stop { self.master_stop(); } - Ok(()) + result } async fn write_dma_internal( @@ -707,13 +716,16 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { let first_length = write[0].len(); let last_slice_index = write.len() - 1; - Self::master_write( + if let Err(err) = Self::master_write( address, first_length.min(255), Stop::Software, (first_length > 255) || (last_slice_index != 0), &check_timeout, - )?; + ) { + self.master_stop(); + return Err(err); + } for (idx, slice) in write.iter().enumerate() { let slice_len = slice.len(); @@ -726,27 +738,36 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { let last_chunk_idx = total_chunks.saturating_sub(1); if idx != 0 { - Self::master_continue( + if let Err(err) = Self::master_continue( slice_len.min(255), (idx != last_slice_index) || (slice_len > 255), &check_timeout, - )?; + ) { + self.master_stop(); + return Err(err); + } } for (number, chunk) in slice.chunks(255).enumerate() { if number != 0 { - Self::master_continue( + if let Err(err) = Self::master_continue( chunk.len(), (number != last_chunk_idx) || (idx != last_slice_index), &check_timeout, - )?; + ) { + self.master_stop(); + return Err(err); + } } for byte in chunk { // Wait until we are allowed to send data // (START has been ACKed or last byte when // through) - self.wait_txe(&check_timeout)?; + if let Err(err) = self.wait_txe(&check_timeout) { + self.master_stop(); + return Err(err); + } // Put byte on the wire //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); @@ -755,10 +776,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { } } // Wait until the write finishes - self.wait_tc(&check_timeout)?; + let result = self.wait_tc(&check_timeout); self.master_stop(); - - Ok(()) + result } pub fn blocking_write_vectored(&mut self, address: u8, write: &[&[u8]]) -> Result<(), Error> { From 91c1d17f166541c5dafc765e952486f21841e120 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 11 Jul 2023 12:38:53 +0200 Subject: [PATCH 067/148] rp/gpio: fix is_set_high/is_set_low, expand tests. --- embassy-rp/src/gpio.rs | 4 ++-- tests/rp/src/bin/gpio.rs | 36 ++++++++++++++++++++++++++++++++++-- tests/stm32/src/bin/gpio.rs | 36 ++++++++++++++++++++++++++++++++++-- 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index d18fb909..a3d330cd 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -566,13 +566,13 @@ impl<'d, T: Pin> Flex<'d, T> { /// Is the output level high? #[inline] pub fn is_set_high(&self) -> bool { - (self.pin.sio_out().value().read() & self.bit()) == 0 + !self.is_set_low() } /// Is the output level low? #[inline] pub fn is_set_low(&self) -> bool { - !self.is_set_high() + (self.pin.sio_out().value().read() & self.bit()) == 0 } /// What level output is set to diff --git a/tests/rp/src/bin/gpio.rs b/tests/rp/src/bin/gpio.rs index 51112d31..946b7dc8 100644 --- a/tests/rp/src/bin/gpio.rs +++ b/tests/rp/src/bin/gpio.rs @@ -21,14 +21,46 @@ async fn main(_spawner: Spawner) { let b = Input::new(&mut b, Pull::None); { - let _a = Output::new(&mut a, Level::Low); + let a = Output::new(&mut a, Level::Low); delay(); assert!(b.is_low()); + assert!(!b.is_high()); + assert!(a.is_set_low()); + assert!(!a.is_set_high()); } { - let _a = Output::new(&mut a, Level::High); + let mut a = Output::new(&mut a, Level::High); + delay(); + assert!(!b.is_low()); + assert!(b.is_high()); + assert!(!a.is_set_low()); + assert!(a.is_set_high()); + + // Test is_set_low / is_set_high + a.set_low(); + delay(); + assert!(b.is_low()); + assert!(a.is_set_low()); + assert!(!a.is_set_high()); + + a.set_high(); delay(); assert!(b.is_high()); + assert!(!a.is_set_low()); + assert!(a.is_set_high()); + + // Test toggle + a.toggle(); + delay(); + assert!(b.is_low()); + assert!(a.is_set_low()); + assert!(!a.is_set_high()); + + a.toggle(); + delay(); + assert!(b.is_high()); + assert!(!a.is_set_low()); + assert!(a.is_set_high()); } } diff --git a/tests/stm32/src/bin/gpio.rs b/tests/stm32/src/bin/gpio.rs index 67f44317..aad17443 100644 --- a/tests/stm32/src/bin/gpio.rs +++ b/tests/stm32/src/bin/gpio.rs @@ -40,14 +40,46 @@ async fn main(_spawner: Spawner) { let b = Input::new(&mut b, Pull::None); { - let _a = Output::new(&mut a, Level::Low, Speed::Low); + let a = Output::new(&mut a, Level::Low, Speed::Low); delay(); assert!(b.is_low()); + assert!(!b.is_high()); + assert!(a.is_set_low()); + assert!(!a.is_set_high()); } { - let _a = Output::new(&mut a, Level::High, Speed::Low); + let mut a = Output::new(&mut a, Level::High, Speed::Low); + delay(); + assert!(!b.is_low()); + assert!(b.is_high()); + assert!(!a.is_set_low()); + assert!(a.is_set_high()); + + // Test is_set_low / is_set_high + a.set_low(); + delay(); + assert!(b.is_low()); + assert!(a.is_set_low()); + assert!(!a.is_set_high()); + + a.set_high(); delay(); assert!(b.is_high()); + assert!(!a.is_set_low()); + assert!(a.is_set_high()); + + // Test toggle + a.toggle(); + delay(); + assert!(b.is_low()); + assert!(a.is_set_low()); + assert!(!a.is_set_high()); + + a.toggle(); + delay(); + assert!(b.is_high()); + assert!(!a.is_set_low()); + assert!(a.is_set_high()); } } From 6f4172fbc1280fdd9190ccddcf3cf6f25788c7be Mon Sep 17 00:00:00 2001 From: goueslati Date: Tue, 11 Jul 2023 16:07:33 +0100 Subject: [PATCH 068/148] wip: added MAC commands --- embassy-stm32-wpan/src/consts.rs | 2 + embassy-stm32-wpan/src/sub/mac/commands.rs | 426 +++++++++++++++--- embassy-stm32-wpan/src/sub/mac/mod.rs | 45 +- embassy-stm32-wpan/src/sub/mac/responses.rs | 0 embassy-stm32-wpan/src/sub/mac/typedefs.rs | 97 ++++ examples/stm32wb/Cargo.toml | 2 +- examples/stm32wb/src/bin/mac_ffd.rs | 174 +++++++ .../src/bin/{tl_mbox_mac_2.rs => mac_rfd.rs} | 63 ++- 8 files changed, 718 insertions(+), 91 deletions(-) create mode 100644 embassy-stm32-wpan/src/sub/mac/responses.rs create mode 100644 embassy-stm32-wpan/src/sub/mac/typedefs.rs create mode 100644 examples/stm32wb/src/bin/mac_ffd.rs rename examples/stm32wb/src/bin/{tl_mbox_mac_2.rs => mac_rfd.rs} (72%) diff --git a/embassy-stm32-wpan/src/consts.rs b/embassy-stm32-wpan/src/consts.rs index 1c84addb..bd70851e 100644 --- a/embassy-stm32-wpan/src/consts.rs +++ b/embassy-stm32-wpan/src/consts.rs @@ -6,6 +6,8 @@ use crate::PacketHeader; #[derive(Debug)] #[repr(C)] pub enum TlPacketType { + MacCmd = 0x00, + BleCmd = 0x01, AclData = 0x02, BleEvt = 0x04, diff --git a/embassy-stm32-wpan/src/sub/mac/commands.rs b/embassy-stm32-wpan/src/sub/mac/commands.rs index 75a31d2f..3c234a3c 100644 --- a/embassy-stm32-wpan/src/sub/mac/commands.rs +++ b/embassy-stm32-wpan/src/sub/mac/commands.rs @@ -1,13 +1,99 @@ -use bit_field::BitField; - use super::opcodes::OpcodeM4ToM0; +use super::typedefs::{AddressMode, GtsCharacteristics, MacAddress, PibId}; pub trait MacCommand { - type Response; const OPCODE: OpcodeM4ToM0; const SIZE: usize; - fn copy_into_slice(&self, buf: &mut [u8]); + fn copy_into_slice(&self, buf: &mut [u8]) { + unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, 8) }; + } +} + +/// MLME ASSOCIATE Request used to request an association +pub struct AssociateRequest { + /// the logical channel on which to attempt association + pub channel_number: u8, + /// the channel page on which to attempt association + pub channel_page: u8, + /// coordinator addressing mode + pub coord_addr_mode: AddressMode, + /// operational capabilities of the associating device + pub capability_information: u8, + /// the identifier of the PAN with which to associate + pub coord_pan_id: [u8; 2], + /// the security level to be used + pub security_level: u8, + /// the mode used to identify the key to be used + pub key_id_mode: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], + /// Coordinator address + pub coord_address: MacAddress, + /// the index of the key to be used + pub key_index: u8, +} + +impl MacCommand for AssociateRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateReq; + const SIZE: usize = 25; +} + +/// MLME DISASSOCIATE Request sed to request a disassociation +pub struct DisassociateRequest { + /// device addressing mode used + pub device_addr_mode: AddressMode, + /// the identifier of the PAN of the device + pub device_pan_id: [u8; 2], + /// the reason for the disassociation + pub disassociate_reason: u8, + /// device address + pub device_address: MacAddress, + /// `true` if the disassociation notification command is to be sent indirectly + pub tx_indirect: bool, + /// the security level to be used + pub security_level: u8, + /// the mode to be used to indetify the key to be used + pub key_id_mode: u8, + /// the index of the key to be used + pub key_index: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], +} + +impl MacCommand for DisassociateRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDisassociateReq; + const SIZE: usize = 24; +} + +/// MLME GET Request used to request a PIB value +pub struct GetRequest { + /// the name of the PIB attribute to read + pub pib_attribute: PibId, +} + +impl MacCommand for GetRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq; + const SIZE: usize = 4; +} + +/// MLME GTS Request used to request and maintain GTSs +pub struct GtsRequest { + /// the characteristics of the GTS + pub characteristics: GtsCharacteristics, + /// the security level to be used + pub security_level: u8, + /// the mode used to identify the key to be used + pub key_id_mode: u8, + /// the index of the key to be used + pub key_index: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], +} + +impl MacCommand for GtsRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq; + const SIZE: usize = 12; } pub struct ResetRequest { @@ -16,68 +102,302 @@ pub struct ResetRequest { } impl MacCommand for ResetRequest { - type Response = (); const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeResetReq; const SIZE: usize = 4; +} + +/// MLME RX ENABLE Request used to request that the receiver is either enabled +/// for a finite period of time or disabled +pub struct RxEnableRequest { + /// the request operation can be deferred or not + pub defer_permit: bool, + /// configure the transceiver to RX with ranging for a value of + /// RANGING_ON or to not enable ranging for RANGING_OFF + pub ranging_rx_control: u8, + /// number of symbols measured before the receiver is to be enabled or disabled + pub rx_on_time: [u8; 4], + /// number of symbols for which the receiver is to be enabled + pub rx_on_duration: [u8; 4], +} + +impl MacCommand for RxEnableRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeRxEnableReq; + const SIZE: usize = 12; fn copy_into_slice(&self, buf: &mut [u8]) { - buf[0] = self.set_default_pib as u8; + buf[0] = self.defer_permit as u8; + buf[1] = self.ranging_rx_control as u8; + + // stuffing to keep 32bit alignment + buf[2] = 0; + buf[3] = 0; + + buf[4..8].copy_from_slice(&self.rx_on_time); + buf[8..12].copy_from_slice(&self.rx_on_duration); } } -#[repr(C)] -pub struct SetRequest { - pub pib_attribute_ptr: *const u8, - pub pib_attribute: u8, - pub stuffing: [u8; 3], -} - -impl MacCommand for SetRequest { - type Response = (); - const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSetReq; - const SIZE: usize = 8; - - fn copy_into_slice(&self, buf: &mut [u8]) { - let address = self.pib_attribute_ptr as usize; - - // 68 ff 2 20 6f - - let a = unsafe { core::slice::from_raw_parts(&self as *const _ as *const u8, Self::SIZE) }; - debug!("{:#04x}", a); - - unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, 8) }; - - // buf[0] = self.pib_attribute_ptr as u8; - // buf[1] = self.pib_attribute; - } -} - -pub struct AssociateRequest { - pub channel_number: u8, +/// MLME SCAN Request used to initiate a channel scan over a given list of channels +pub struct ScanRequest { + /// the type of scan to be performed + pub scan_type: u8, + /// the time spent on scanning each channel + pub scan_duration: u8, + /// channel page on which to perform the scan pub channel_page: u8, - pub coord_addr_mode: u8, - pub capability_information: u8, - pub coord_pan_id: [u8; 2], + /// security level to be used pub security_level: u8, - pub key_id_mode: u8, + /// indicate which channels are to be scanned + pub scan_channels: [u8; 4], + /// originator the key to be used pub key_source: [u8; 8], - pub coord_address: MacAddress, + /// mode used to identify the key to be used + pub key_id_mode: u8, + /// index of the key to be used pub key_index: u8, } -impl MacCommand for AssociateRequest { - const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateReq; - const SIZE: usize = 25; - type Response = (); - - fn copy_into_slice(&self, buf: &mut [u8]) { - let a = unsafe { core::slice::from_raw_parts(&self as *const _ as *const u8, core::mem::size_of::()) }; - - buf[..a.len()].copy_from_slice(a); - } +impl MacCommand for ScanRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeScanReq; + const SIZE: usize = 20; } -pub union MacAddress { - pub short: [u8; 2], - pub extended: [u8; 8], +/// MLME SET Request used to attempt to write the given value to the indicated PIB attribute +#[repr(C)] +pub struct SetRequest { + /// the pointer to the value of the PIB attribute to set + pub pib_attribute_ptr: *const u8, + /// the name of the PIB attribute to set + pub pib_attribute: PibId, +} + +impl MacCommand for SetRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSetReq; + const SIZE: usize = 8; +} + +/// MLME START Request used by the FFDs to intiate a new PAN or to begin using a new superframe +/// configuration +#[derive(Default)] +pub struct StartRequest { + /// PAN indentifier to used by the device + pub pan_id: [u8; 2], + /// logical channel on which to begin + pub channel_number: u8, + /// channel page on which to begin + pub channel_page: u8, + /// time at which to begin transmitting beacons + pub start_time: [u8; 4], + /// indicated how often the beacon is to be transmitted + pub beacon_order: u8, + /// length of the active portion of the superframe + pub superframe_order: u8, + /// indicated wheter the device is a PAN coordinator or not + pub pan_coordinator: bool, + /// indicates if the receiver of the beaconing device is disabled or not + pub battery_life_extension: bool, + /// indicated if the coordinator realignment command is to be trasmitted + pub coord_realignment: u8, + /// indicated if the coordinator realignment command is to be trasmitted + pub coord_realign_security_level: u8, + /// index of the key to be used + pub coord_realign_key_id_index: u8, + /// originator of the key to be used + pub coord_realign_key_source: [u8; 8], + /// security level to be used for beacon frames + pub beacon_security_level: u8, + /// mode used to identify the key to be used + pub beacon_key_id_mode: u8, + /// index of the key to be used + pub beacon_key_index: u8, + /// originator of the key to be used + pub beacon_key_source: [u8; 8], +} + +impl MacCommand for StartRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeStartReq; + const SIZE: usize = 35; +} + +/// MLME SYNC Request used to synchronize with the coordinator by acquiring and, if +/// specified, tracking its beacons +pub struct SyncRequest { + /// the channel number on which to attempt coordinator synchronization + pub channel_number: u8, + /// the channel page on which to attempt coordinator synchronization + pub channel_page: u8, + /// `true` if the MLME is to synchronize with the next beacon and attempts + /// to track all future beacons. + /// + /// `false` if the MLME is to synchronize with only the next beacon + pub track_beacon: bool, +} + +impl MacCommand for SyncRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSyncReq; + const SIZE: usize = 4; +} + +/// MLME POLL Request propmts the device to request data from the coordinator +pub struct PollRequest { + /// addressing mode of the coordinator + pub coord_addr_mode: AddressMode, + /// security level to be used + pub security_level: u8, + /// mode used to identify the key to be used + pub key_id_mode: u8, + /// index of the key to be used + pub key_index: u8, + /// coordinator address + pub coord_address: MacAddress, + /// originator of the key to be used + pub key_source: [u8; 8], + /// PAN identifier of the coordinator + pub coord_pan_id: [u8; 2], +} + +impl MacCommand for PollRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmePollReq; + const SIZE: usize = 24; +} + +/// MLME DPS Request allows the next higher layer to request that the PHY utilize a +/// given pair of preamble codes for a single use pending expiration of the DPSIndexDuration +pub struct DpsRequest { + /// the index value for the transmitter + tx_dps_index: u8, + /// the index value of the receiver + rx_dps_index: u8, + /// the number of symbols for which the transmitter and receiver will utilize the + /// respective DPS indices + dps_index_duration: u8, +} + +impl MacCommand for DpsRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDpsReq; + const SIZE: usize = 4; +} + +/// MLME SOUNDING request primitive which is used by the next higher layer to request that +/// the PHY respond with channel sounding information +pub struct SoundingRequest; + +impl MacCommand for SoundingRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSoundingReq; + const SIZE: usize = 4; +} + +/// MLME CALIBRATE request primitive which used to obtain the results of a ranging +/// calibration request from an RDEV +pub struct CalibrateRequest; + +impl MacCommand for CalibrateRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeCalibrateReq; + const SIZE: usize = 4; +} + +/// MCPS DATA Request used for MAC data related requests from the application +pub struct DataRequest { + /// the handle assocated with the MSDU to be transmitted + pub msdu_ptr: *const u8, + /// source addressing mode used + pub src_addr_mode: AddressMode, + /// destination addressing mode used + pub dst_addr_mode: AddressMode, + /// destination PAN Id + pub dst_pan_id: [u8; 2], + /// destination address + pub dst_address: MacAddress, + /// the number of octets contained in the MSDU + pub msdu_length: u8, + /// the handle assocated with the MSDU to be transmitted + pub msdu_handle: u8, + /// the ACK transmittion options for the MSDU + pub ack_tx: u8, + /// `true` if a GTS is to be used for transmission + /// + /// `false` indicates that the CAP will be used + pub gts_tx: bool, + /// the pending bit transmission options for the MSDU + pub indirect_tx: u8, + /// the security level to be used + pub security_level: u8, + /// the mode used to indentify the key to be used + pub key_id_mode: u8, + /// the index of the key to be used + pub key_index: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], + /// 2011 - the pulse repitition value + pub uwbprf: u8, + /// 2011 - the ranging configuration + pub ranging: u8, + /// 2011 - the preamble symbol repititions + pub uwb_preamble_symbol_repetitions: u8, + /// 2011 - indicates the data rate + pub datrate: u8, +} + +impl MacCommand for DataRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsDataReq; + const SIZE: usize = 40; +} + +/// for MCPS PURGE Request used to purge an MSDU from the transaction queue +pub struct PurgeRequest { + /// the handle associated with the MSDU to be purged from the transaction + /// queue + pub msdu_handle: u8, +} + +impl MacCommand for PurgeRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsPurgeReq; + const SIZE: usize = 4; +} + +/// MLME ASSOCIATE Response used to initiate a response to an MLME-ASSOCIATE.indication +pub struct AssociateResponse { + /// extended address of the device requesting association + pub device_address: [u8; 8], + /// 16-bitshort device address allocated by the coordinator on successful + /// association + pub assoc_short_address: [u8; 2], + /// status of the association attempt + pub status: u8, + /// security level to be used + pub security_level: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], + /// the mode used to identify the key to be used + pub key_id_mode: u8, + /// the index of the key to be used + pub key_index: u8, +} + +impl MacCommand for AssociateResponse { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateRes; + const SIZE: usize = 24; +} + +/// MLME ORPHAN Response used to respond to the MLME ORPHAN Indication +pub struct OrphanResponse { + /// extended address of the orphaned device + pub orphan_address: [u8; 8], + /// short address allocated to the orphaned device + pub short_address: [u8; 2], + /// if the orphaned device is associated with coordinator or not + pub associated_member: bool, + /// security level to be used + pub security_level: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], + /// the mode used to identify the key to be used + pub key_id_mode: u8, + /// the index of the key to be used + pub key_index: u8, +} + +impl MacCommand for OrphanResponse { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeOrphanRes; + const SIZE: usize = 24; } diff --git a/embassy-stm32-wpan/src/sub/mac/mod.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs index 83970a88..8e117d97 100644 --- a/embassy-stm32-wpan/src/sub/mac/mod.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -9,14 +9,17 @@ use embassy_stm32::ipcc::Ipcc; use embassy_sync::waitqueue::AtomicWaker; use self::commands::MacCommand; +use self::typedefs::MacStatus; use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::{EvtBox, EvtPacket}; use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; use crate::{channels, evt}; -pub mod commands; mod opcodes; +pub mod commands; +pub mod responses; +pub mod typedefs; static MAC_WAKER: AtomicWaker = AtomicWaker::new(); static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false); @@ -59,12 +62,25 @@ impl Mac { /// `HW_IPCC_MAC_802_15_4_CmdEvtNot` pub async fn write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { self.write(opcode, payload).await; - Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await; + Ipcc::flush(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL).await; unsafe { let p_event_packet = MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket; let p_mac_rsp_evt = &((*p_event_packet).evt_serial.evt.payload) as *const u8; + let evt_serial = (MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket) + .read_volatile() + .evt_serial; + let kind = (evt_serial).kind; + let evt_code = evt_serial.evt.evt_code; + let payload_len = evt_serial.evt.payload_len; + let payload = evt_serial.evt.payload; + + debug!( + "evt kind {} evt_code {} len {} payload {}", + kind, evt_code, payload_len, payload + ); + ptr::read_volatile(p_mac_rsp_evt) } } @@ -74,15 +90,32 @@ impl Mac { Ipcc::send(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL, || unsafe { CmdPacket::write_into( MAC_802_15_4_CMD_BUFFER.as_mut_ptr(), - TlPacketType::OtCmd, + TlPacketType::MacCmd, opcode, payload, ); }) .await; + + unsafe { + let typ = MAC_802_15_4_CMD_BUFFER.as_ptr().read_volatile().cmdserial.ty; + let cmd_code = MAC_802_15_4_CMD_BUFFER.as_ptr().read_volatile().cmdserial.cmd.cmd_code; + let payload_len = MAC_802_15_4_CMD_BUFFER + .as_ptr() + .read_volatile() + .cmdserial + .cmd + .payload_len; + let payload = MAC_802_15_4_CMD_BUFFER.as_ptr().read_volatile().cmdserial.cmd.payload; + + debug!( + "serial type {} cmd_code {} len {} payload {}", + typ, cmd_code, payload_len, payload + ); + } } - pub async fn send_command(&self, cmd: T) -> u8 + pub async fn send_command(&self, cmd: T) -> Result where T: MacCommand, { @@ -91,7 +124,9 @@ impl Mac { debug!("sending {:#x}", payload[..T::SIZE]); - self.write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]).await + let response = self.write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]).await; + + MacStatus::try_from(response) } } diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs new file mode 100644 index 00000000..e69de29b diff --git a/embassy-stm32-wpan/src/sub/mac/typedefs.rs b/embassy-stm32-wpan/src/sub/mac/typedefs.rs new file mode 100644 index 00000000..d43d6e0c --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/typedefs.rs @@ -0,0 +1,97 @@ +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum MacStatus { + Success = 0x00, + Error = 0x01, + NotImplemented = 0x02, + NotSupported = 0x03, + HardwareNotSupported = 0x04, + Undefined = 0x05, +} + +impl TryFrom for MacStatus { + type Error = (); + + fn try_from(value: u8) -> Result>::Error> { + match value { + 0x00 => Ok(Self::Success), + 0x01 => Ok(Self::Error), + 0x02 => Ok(Self::NotImplemented), + 0x03 => Ok(Self::NotSupported), + 0x04 => Ok(Self::HardwareNotSupported), + 0x05 => Ok(Self::Undefined), + _ => Err(()), + } + } +} + +/// this enum contains all the MAC PIB Ids +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum PibId { + // PHY + CurrentChannel = 0x00, + ChannelsSupported = 0x01, + TransmitPower = 0x02, + CCAMode = 0x03, + CurrentPage = 0x04, + MaxFrameDuration = 0x05, + SHRDuration = 0x06, + SymbolsPerOctet = 0x07, + + // MAC + AckWaitDuration = 0x40, + AssociationPermit = 0x41, + AutoRequest = 0x42, + BeaconPayload = 0x45, + BeaconPayloadLength = 0x46, + BeaconOrder = 0x47, + Bsn = 0x49, + CoordExtendedAdddress = 0x4A, + CoordShortAddress = 0x4B, + Dsn = 0x4C, + MaxFrameTotalWaitTime = 0x58, + MaxFrameRetries = 0x59, + PanId = 0x50, + ResponseWaitTime = 0x5A, + RxOnWhenIdle = 0x52, + SecurityEnabled = 0x5D, + ShortAddress = 0x53, + SuperframeOrder = 0x54, + TimestampSupported = 0x5C, + TransactionPersistenceTime = 0x55, + MaxBe = 0x57, + LifsPeriod = 0x5E, + SifsPeriod = 0x5F, + MaxCsmaBackoffs = 0x4E, + MinBe = 0x4F, + PanCoordinator = 0x10, + AssocPanCoordinator = 0x11, + ExtendedAddress = 0x6F, + AclEntryDescriptor = 0x70, + AclEntryDescriptorSize = 0x71, + DefaultSecurity = 0x72, + DefaultSecurityMaterialLength = 0x73, + DefaultSecurityMaterial = 0x74, + DefaultSecuritySuite = 0x75, + SecurityMode = 0x76, + CurrentAclEntries = 0x80, + DefaultSecurityExtendedAddress = 0x81, + AssociatedPanCoordinator = 0x56, + PromiscuousMode = 0x51, +} + +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum AddressMode { + NoAddress = 0x00, + Reserved = 0x01, + Short = 0x02, + Extended = 0x03, +} + +pub union MacAddress { + pub short: [u8; 2], + pub extended: [u8; 8], +} + +pub struct GtsCharacteristics { + pub fields: u8, +} diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 10973454..f23c8afa 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -36,7 +36,7 @@ name = "tl_mbox_mac" required-features = ["mac"] [[bin]] -name = "tl_mbox_mac_2" +name = "mac_ffd" required-features = ["mac"] [[bin]] diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs new file mode 100644 index 00000000..4100d1ac --- /dev/null +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -0,0 +1,174 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::bind_interrupts; +use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32_wpan::sub::mac::commands::{ResetRequest, SetRequest, StartRequest}; +use embassy_stm32_wpan::sub::mac::typedefs::PibId; +use embassy_stm32_wpan::sub::mm; +use embassy_stm32_wpan::TlMbox; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs{ + IPCC_C1_RX => ReceiveInterruptHandler; + IPCC_C1_TX => TransmitInterruptHandler; +}); + +#[embassy_executor::task] +async fn run_mm_queue(memory_manager: mm::MemoryManager) { + memory_manager.run_queue().await; +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + /* + How to make this work: + + - Obtain a NUCLEO-STM32WB55 from your preferred supplier. + - Download and Install STM32CubeProgrammer. + - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from + gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x + - Open STM32CubeProgrammer + - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. + - Once complete, click connect to connect to the device. + - On the left hand pane, click the RSS signal icon to open "Firmware Upgrade Services". + - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file + - Select that file, the memory address, "verify download", and then "Firmware Upgrade". + - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the + stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. + - Select that file, the memory address, "verify download", and then "Firmware Upgrade". + - Select "Start Wireless Stack". + - Disconnect from the device. + - In the examples folder for stm32wb, modify the memory.x file to match your target device. + - Run this example. + + Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. + */ + + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + + let config = Config::default(); + let mbox = TlMbox::init(p.IPCC, Irqs, config); + + spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + + let sys_event = mbox.sys_subsystem.read().await; + info!("sys event: {}", sys_event.payload()); + + core::mem::drop(sys_event); + + let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; + info!("initialized mac: {}", result); + + info!("resetting"); + let response = mbox + .mac_subsystem + .send_command(ResetRequest { set_default_pib: true }) + .await; + info!("{}", response); + + info!("setting extended address"); + let extended_address: u64 = 0xACDE480000000001; + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &extended_address as *const _ as *const u8, + pib_attribute: PibId::ExtendedAddress, + }) + .await; + info!("{}", response); + + info!("setting short address"); + let short_address: u16 = 0x1122; + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &short_address as *const _ as *const u8, + pib_attribute: PibId::ShortAddress, + }) + .await; + info!("{}", response); + + info!("setting association permit"); + let association_permit: bool = true; + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &association_permit as *const _ as *const u8, + pib_attribute: PibId::AssociationPermit, + }) + .await; + info!("{}", response); + + info!("setting TX power"); + let transmit_power: i8 = 2; + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &transmit_power as *const _ as *const u8, + pib_attribute: PibId::TransmitPower, + }) + .await; + info!("{}", response); + + info!("starting FFD device"); + let response = mbox + .mac_subsystem + .send_command(StartRequest { + channel_number: 16, + beacon_order: 0x0F, + superframe_order: 0x0F, + pan_coordinator: true, + battery_life_extension: false, + ..Default::default() + }) + .await; + info!("{}", response); + + info!("setting RX on when idle"); + let rx_on_while_idle: bool = true; + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, + pib_attribute: PibId::RxOnWhenIdle, + }) + .await; + info!("{}", response); + + // info!("association request"); + // mbox.mac_subsystem + // .send_command(AssociateRequest { + // channel_number: 16, + // channel_page: 0, + // coord_addr_mode: 2, + // coord_address: MacAddress { short: [0x22, 0x11] }, + // capability_information: 0x80, + // coord_pan_id: [0xAA, 0x1A], + // security_level: 0, + + // key_id_mode: 0, + // key_index: 0, + // key_source: [0; 8], + // }) + // .await; + // info!("reading"); + // let result = mbox.mac_subsystem.read().await; + // info!("{}", result.payload()); + + // + // info!("starting ble..."); + // mbox.ble_subsystem.t_write(0x0c, &[]).await; + // + // info!("waiting for ble..."); + // let ble_event = mbox.ble_subsystem.tl_read().await; + // + // info!("ble event: {}", ble_event.payload()); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} diff --git a/examples/stm32wb/src/bin/tl_mbox_mac_2.rs b/examples/stm32wb/src/bin/mac_rfd.rs similarity index 72% rename from examples/stm32wb/src/bin/tl_mbox_mac_2.rs rename to examples/stm32wb/src/bin/mac_rfd.rs index e069adf8..938fe754 100644 --- a/examples/stm32wb/src/bin/tl_mbox_mac_2.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -6,7 +6,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, MacAddress, ResetRequest, SetRequest}; +use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, ResetRequest, SetRequest, StartRequest}; +use embassy_stm32_wpan::sub::mac::typedefs::{AddressMode, MacAddress, PibId}; use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -71,46 +72,44 @@ async fn main(spawner: Spawner) { info!("{}", response); info!("setting extended address"); - let extended_address: u64 = 0xACDE480000000001; - defmt::debug!("{}", &extended_address as *const _ as *const u8); + let extended_address: u64 = 0xACDE480000000002; let response = mbox .mac_subsystem .send_command(SetRequest { pib_attribute_ptr: &extended_address as *const _ as *const u8, - pib_attribute: 0x6F, - stuffing: [0; 3], + pib_attribute: PibId::ExtendedAddress, }) .await; info!("{}", response); - // info!("association request"); - // mbox.mac_subsystem - // .send_command(AssociateRequest { - // channel_number: 16, - // channel_page: 0, - // coord_addr_mode: 2, - // coord_address: MacAddress { short: [0x22, 0x11] }, - // capability_information: 0x80, - // coord_pan_id: [0xAA, 0x1A], - // security_level: 0, + info!("assocation request"); + let response = mbox + .mac_subsystem + .send_command(AssociateRequest { + channel_number: 16, + channel_page: 0, + coord_addr_mode: AddressMode::Short, + coord_address: MacAddress { short: [0x22, 0x11] }, + capability_information: 0x80, + coord_pan_id: [0xAA, 0x1A], + security_level: 0x00, + key_id_mode: 0, + key_source: [0; 8], + key_index: 0, + }) + .await; + info!("{}", response); - // key_id_mode: 0, - // key_index: 0, - // key_source: [0; 8], - // }) - // .await; - // info!("reading"); - // let result = mbox.mac_subsystem.read().await; - // info!("{}", result.payload()); - - // - // info!("starting ble..."); - // mbox.ble_subsystem.t_write(0x0c, &[]).await; - // - // info!("waiting for ble..."); - // let ble_event = mbox.ble_subsystem.tl_read().await; - // - // info!("ble event: {}", ble_event.payload()); + info!("setting short address"); + let short: u64 = 0xACDE480000000002; + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &short as *const _ as *const u8, + pib_attribute: PibId::ShortAddress, + }) + .await; + info!("{}", response); info!("Test OK"); cortex_m::asm::bkpt(); From 67b14e6e7a98abc538adda45d6434ad44d700283 Mon Sep 17 00:00:00 2001 From: goueslati Date: Tue, 11 Jul 2023 16:54:48 +0100 Subject: [PATCH 069/148] wip: added MAC responses --- embassy-stm32-wpan/src/sub/mac/commands.rs | 17 ++ embassy-stm32-wpan/src/sub/mac/consts.rs | 3 + embassy-stm32-wpan/src/sub/mac/mod.rs | 3 +- embassy-stm32-wpan/src/sub/mac/responses.rs | 168 ++++++++++++++++++++ embassy-stm32-wpan/src/sub/mac/typedefs.rs | 27 ++++ 5 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 embassy-stm32-wpan/src/sub/mac/consts.rs diff --git a/embassy-stm32-wpan/src/sub/mac/commands.rs b/embassy-stm32-wpan/src/sub/mac/commands.rs index 3c234a3c..4965a46e 100644 --- a/embassy-stm32-wpan/src/sub/mac/commands.rs +++ b/embassy-stm32-wpan/src/sub/mac/commands.rs @@ -11,6 +11,7 @@ pub trait MacCommand { } /// MLME ASSOCIATE Request used to request an association +#[repr(C)] pub struct AssociateRequest { /// the logical channel on which to attempt association pub channel_number: u8, @@ -40,6 +41,7 @@ impl MacCommand for AssociateRequest { } /// MLME DISASSOCIATE Request sed to request a disassociation +#[repr(C)] pub struct DisassociateRequest { /// device addressing mode used pub device_addr_mode: AddressMode, @@ -67,6 +69,7 @@ impl MacCommand for DisassociateRequest { } /// MLME GET Request used to request a PIB value +#[repr(C)] pub struct GetRequest { /// the name of the PIB attribute to read pub pib_attribute: PibId, @@ -78,6 +81,7 @@ impl MacCommand for GetRequest { } /// MLME GTS Request used to request and maintain GTSs +#[repr(C)] pub struct GtsRequest { /// the characteristics of the GTS pub characteristics: GtsCharacteristics, @@ -96,6 +100,7 @@ impl MacCommand for GtsRequest { const SIZE: usize = 12; } +#[repr(C)] pub struct ResetRequest { /// MAC PIB attributes are set to their default values or not during reset pub set_default_pib: bool, @@ -108,6 +113,7 @@ impl MacCommand for ResetRequest { /// MLME RX ENABLE Request used to request that the receiver is either enabled /// for a finite period of time or disabled +#[repr(C)] pub struct RxEnableRequest { /// the request operation can be deferred or not pub defer_permit: bool, @@ -138,6 +144,7 @@ impl MacCommand for RxEnableRequest { } /// MLME SCAN Request used to initiate a channel scan over a given list of channels +#[repr(C)] pub struct ScanRequest { /// the type of scan to be performed pub scan_type: u8, @@ -179,6 +186,7 @@ impl MacCommand for SetRequest { /// MLME START Request used by the FFDs to intiate a new PAN or to begin using a new superframe /// configuration #[derive(Default)] +#[repr(C)] pub struct StartRequest { /// PAN indentifier to used by the device pub pan_id: [u8; 2], @@ -221,6 +229,7 @@ impl MacCommand for StartRequest { /// MLME SYNC Request used to synchronize with the coordinator by acquiring and, if /// specified, tracking its beacons +#[repr(C)] pub struct SyncRequest { /// the channel number on which to attempt coordinator synchronization pub channel_number: u8, @@ -239,6 +248,7 @@ impl MacCommand for SyncRequest { } /// MLME POLL Request propmts the device to request data from the coordinator +#[repr(C)] pub struct PollRequest { /// addressing mode of the coordinator pub coord_addr_mode: AddressMode, @@ -263,6 +273,7 @@ impl MacCommand for PollRequest { /// MLME DPS Request allows the next higher layer to request that the PHY utilize a /// given pair of preamble codes for a single use pending expiration of the DPSIndexDuration +#[repr(C)] pub struct DpsRequest { /// the index value for the transmitter tx_dps_index: u8, @@ -280,6 +291,7 @@ impl MacCommand for DpsRequest { /// MLME SOUNDING request primitive which is used by the next higher layer to request that /// the PHY respond with channel sounding information +#[repr(C)] pub struct SoundingRequest; impl MacCommand for SoundingRequest { @@ -289,6 +301,7 @@ impl MacCommand for SoundingRequest { /// MLME CALIBRATE request primitive which used to obtain the results of a ranging /// calibration request from an RDEV +#[repr(C)] pub struct CalibrateRequest; impl MacCommand for CalibrateRequest { @@ -297,6 +310,7 @@ impl MacCommand for CalibrateRequest { } /// MCPS DATA Request used for MAC data related requests from the application +#[repr(C)] pub struct DataRequest { /// the handle assocated with the MSDU to be transmitted pub msdu_ptr: *const u8, @@ -344,6 +358,7 @@ impl MacCommand for DataRequest { } /// for MCPS PURGE Request used to purge an MSDU from the transaction queue +#[repr(C)] pub struct PurgeRequest { /// the handle associated with the MSDU to be purged from the transaction /// queue @@ -356,6 +371,7 @@ impl MacCommand for PurgeRequest { } /// MLME ASSOCIATE Response used to initiate a response to an MLME-ASSOCIATE.indication +#[repr(C)] pub struct AssociateResponse { /// extended address of the device requesting association pub device_address: [u8; 8], @@ -380,6 +396,7 @@ impl MacCommand for AssociateResponse { } /// MLME ORPHAN Response used to respond to the MLME ORPHAN Indication +#[repr(C)] pub struct OrphanResponse { /// extended address of the orphaned device pub orphan_address: [u8; 8], diff --git a/embassy-stm32-wpan/src/sub/mac/consts.rs b/embassy-stm32-wpan/src/sub/mac/consts.rs new file mode 100644 index 00000000..dfbbadc6 --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/consts.rs @@ -0,0 +1,3 @@ +pub const MAX_ED_SCAN_RESULTS_SUPPORTED: usize = 16; +pub const MAX_PAN_DESC_SUPPORTED: usize = 6; +pub const MAX_SOUNDING_LIST_SUPPORTED: usize = 6; diff --git a/embassy-stm32-wpan/src/sub/mac/mod.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs index 8e117d97..6a3a057f 100644 --- a/embassy-stm32-wpan/src/sub/mac/mod.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -16,8 +16,9 @@ use crate::evt::{EvtBox, EvtPacket}; use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; use crate::{channels, evt}; -mod opcodes; pub mod commands; +mod consts; +mod opcodes; pub mod responses; pub mod typedefs; diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index e69de29b..7b240f37 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -0,0 +1,168 @@ +use super::consts::{MAX_ED_SCAN_RESULTS_SUPPORTED, MAX_PAN_DESC_SUPPORTED, MAX_SOUNDING_LIST_SUPPORTED}; +use super::typedefs::{AddressMode, MacAddress, PanDescriptor}; + +pub trait MacResponse { + const SIZE: usize; + + fn parse(buf: &[u8]) -> Self; +} + +/// MLME ASSOCIATE Confirm used to inform of the initiating device whether +/// its request to associate was successful or unsuccessful +pub struct AssociateConfirm { + /// short address allocated by the coordinator on successful association + pub assoc_short_address: [u8; 2], + /// status of the association request + pub status: u8, + /// security level to be used + pub security_level: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], + /// the mode used to identify the key to be used + pub key_id_mode: u8, + /// the index of the key to be used + pub key_index: u8, +} + +/// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application. +pub struct DisassociateConfirm { + /// status of the disassociation attempt + pub status: u8, + /// device addressing mode used + pub device_addr_mode: AddressMode, + /// the identifier of the PAN of the device + pub device_pan_id: [u8; 2], + /// device address + pub device_address: MacAddress, +} + +/// MLME GET Confirm which requests information about a given PIB attribute +pub struct GetConfirm { + /// The pointer to the value of the PIB attribute attempted to read + pub pib_attribute_value_ptr: *const u8, + /// Status of the GET attempt + pub status: u8, + /// The name of the PIB attribute attempted to read + pub pib_attribute: u8, + /// The lenght of the PIB attribute Value return + pub pib_attribute_value_len: u8, +} + +/// MLME GTS Confirm which eports the results of a request to allocate a new GTS +/// or to deallocate an existing GTS +pub struct GtsConfirm { + /// The characteristics of the GTS + pub gts_characteristics: u8, + /// The status of the GTS reques + pub status: u8, +} + +/// MLME RESET Confirm which is used to report the results of the reset operation +pub struct ResetConfirm { + /// The result of the reset operation + status: u8, +} + +/// MLME RX ENABLE Confirm which is used to report the results of the attempt +/// to enable or disable the receiver +pub struct RxEnableConfirm { + /// Result of the request to enable or disable the receiver + status: u8, +} + +/// MLME SCAN Confirm which is used to report the result of the channel scan request +pub struct ScanConfirm { + /// Status of the scan request + pub status: u8, + /// The type of scan performed + pub scan_type: u8, + /// Channel page on which the scan was performed + pub channel_page: u8, + /// Channels given in the request which were not scanned + pub unscanned_channels: [u8; 4], + /// Number of elements returned in the appropriate result lists + pub result_list_size: u8, + /// List of energy measurements + pub energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED], + /// List of PAN descriptors + pub pan_descriptor_list: [PanDescriptor; MAX_PAN_DESC_SUPPORTED], + /// Categorization of energy detected in channel + pub detected_category: u8, + /// For UWB PHYs, the list of energy measurements taken + pub uwb_energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED], +} + +/// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute +pub struct SetConfirm { + /// The result of the set operation + pub status: u8, + /// The name of the PIB attribute that was written + pub pin_attribute: u8, +} + +/// MLME START Confirm which is used to report the results of the attempt to +/// start using a new superframe configuration +pub struct StartConfirm { + /// Result of the attempt to start using an updated superframe configuration + pub status: u8, +} + +/// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data +pub struct PollConfirm { + /// The status of the data request + pub status: u8, +} + +/// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide +/// channel sounding information +pub struct SoundingConfirm { + /// Results of the sounding measurement + sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED], +} + +/// MLME CALIBRATE Confirm which reports the result of a request to the PHY +/// to provide internal propagation path information +pub struct CalibrateConfirm { + /// The status of the attempt to return sounding data + pub status: u8, + /// A count of the propagation time from the ranging counter + /// to the transmit antenna + pub cal_tx_rmaker_offset: u32, + /// A count of the propagation time from the receive antenna + /// to the ranging counter + pub cal_rx_rmaker_offset: u32, +} + +/// MCPS DATA Confirm which will be used for reporting the results of +/// MAC data related requests from the application +pub struct DataConfirm { + /// The handle associated with the MSDU being confirmed + pub msdu_handle: u8, + /// The time, in symbols, at which the data were transmitted + pub a_time_stamp: [u8; 4], + /// ranging status + pub ranging_received: u8, + /// The status of the last MSDU transmission + pub status: u8, + /// time units corresponding to an RMARKER at the antenna at + /// the beginning of a ranging exchange + pub ranging_counter_start: u32, + /// time units corresponding to an RMARKER at the antenna + /// at the end of a ranging exchange + pub ranging_counter_stop: u32, + /// time units in a message exchange over which the tracking offset was measured + pub ranging_tracking_interval: u32, + /// time units slipped or advanced by the radio tracking system + pub ranging_offset: u32, + /// The FoM characterizing the ranging measurement + pub ranging_fom: u8, +} + +/// MCPS PURGE Confirm which will be used by the MAC to notify the application of +/// the status of its request to purge an MSDU from the transaction queue +pub struct PurgeConfirm { + /// Handle associated with the MSDU requested to be purged from the transaction queue + pub msdu_handle: u8, + /// The status of the request + pub status: u8, +} diff --git a/embassy-stm32-wpan/src/sub/mac/typedefs.rs b/embassy-stm32-wpan/src/sub/mac/typedefs.rs index d43d6e0c..7f0dd75c 100644 --- a/embassy-stm32-wpan/src/sub/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/sub/mac/typedefs.rs @@ -95,3 +95,30 @@ pub union MacAddress { pub struct GtsCharacteristics { pub fields: u8, } + +/// MAC PAN Descriptor which contains the network details of the device from +/// which the beacon is received +pub struct PanDescriptor { + /// PAN identifier of the coordinator + pub a_coord_pan_id: [u8; 2], + /// Coordinator addressing mode + pub coord_addr_mode: AddressMode, + /// The current logical channel occupied by the network + pub logical_channel: u8, + /// Coordinator address + pub coord_addr: MacAddress, + /// The current channel page occupied by the network + pub channel_page: u8, + /// PAN coordinator is accepting GTS requests or not + pub gts_permit: bool, + /// Superframe specification as specified in the received beacon frame + pub a_superframe_spec: [u8; 2], + /// The time at which the beacon frame was received, in symbols + pub a_time_stamp: [u8; 4], + /// The LQI at which the network beacon was received + pub link_quality: u8, + /// Security level purportedly used by the received beacon frame + pub security_level: u8, + /// Byte Stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 2], +} From fbddfcbfb7f732db593eecd5383742d9ce7308e7 Mon Sep 17 00:00:00 2001 From: goueslati Date: Tue, 11 Jul 2023 17:19:32 +0100 Subject: [PATCH 070/148] wip: added MAC indications --- embassy-stm32-wpan/src/sub/mac/consts.rs | 1 + embassy-stm32-wpan/src/sub/mac/indications.rs | 205 ++++++++++++++++++ embassy-stm32-wpan/src/sub/mac/mod.rs | 1 + embassy-stm32-wpan/src/sub/mac/responses.rs | 14 ++ 4 files changed, 221 insertions(+) create mode 100644 embassy-stm32-wpan/src/sub/mac/indications.rs diff --git a/embassy-stm32-wpan/src/sub/mac/consts.rs b/embassy-stm32-wpan/src/sub/mac/consts.rs index dfbbadc6..892d533b 100644 --- a/embassy-stm32-wpan/src/sub/mac/consts.rs +++ b/embassy-stm32-wpan/src/sub/mac/consts.rs @@ -1,3 +1,4 @@ pub const MAX_ED_SCAN_RESULTS_SUPPORTED: usize = 16; pub const MAX_PAN_DESC_SUPPORTED: usize = 6; pub const MAX_SOUNDING_LIST_SUPPORTED: usize = 6; +pub const MAX_PENDING_ADDRESS: usize = 7; diff --git a/embassy-stm32-wpan/src/sub/mac/indications.rs b/embassy-stm32-wpan/src/sub/mac/indications.rs new file mode 100644 index 00000000..ebca16f7 --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/indications.rs @@ -0,0 +1,205 @@ +use super::consts::MAX_PENDING_ADDRESS; +use super::typedefs::{AddressMode, MacAddress, PanDescriptor}; + +/// MLME ASSOCIATE Indication which will be used by the MAC +/// to indicate the reception of an association request command +#[repr(C)] +pub struct AssociateIndication { + /// Extended address of the device requesting association + pub device_address: [u8; 8], + /// Operational capabilities of the device requesting association + pub capability_information: u8, + /// Security level purportedly used by the received MAC command frame + pub security_level: u8, + /// The mode used to identify the key used by the originator of frame + pub key_id_mode: u8, + /// Index of the key used by the originator of the received frame + pub key_index: u8, + /// The originator of the key used by the originator of the received frame + pub key_source: [u8; 8], +} + +/// MLME DISASSOCIATE indication which will be used to send +/// disassociation indication to the application. +#[repr(C)] +pub struct DisassociateIndication { + /// Extended address of the device requesting association + pub device_address: [u8; 8], + /// The reason for the disassociation + pub disassociate_reason: u8, + /// The security level to be used + pub security_level: u8, + /// The mode used to identify the key to be used + pub key_id_mode: u8, + /// The index of the key to be used + pub key_index: u8, + /// The originator of the key to be used + pub key_source: [u8; 8], +} + +/// MLME BEACON NOTIIFY Indication which is used to send parameters contained +/// within a beacon frame received by the MAC to the application +#[repr(C)] +pub struct BeaconNotifyIndication { + /// he set of octets comprising the beacon payload to be transferred + /// from the MAC sublayer entity to the next higher layer + pub sdu_ptr: *const u8, + /// The PAN Descriptor for the received beacon + pub pan_descriptor: PanDescriptor, + /// The list of addresses of the devices + pub addr_list: [MacAddress; MAX_PENDING_ADDRESS], + /// Beacon Sequence Number + pub bsn: u8, + /// The beacon pending address specification + pub pend_addr_spec: u8, + /// Number of octets contained in the beacon payload of the beacon frame + pub sdu_length: u8, +} + +/// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status +#[repr(C)] +pub struct CommStatusIndication { + /// The 16-bit PAN identifier of the device from which the frame + /// was received or to which the frame was being sent + pub pan_id: [u8; 2], + /// Source addressing mode + pub src_addr_mode: AddressMode, + /// Destination addressing mode + pub dst_addr_mode: AddressMode, + /// Source address + pub src_address: MacAddress, + /// Destination address + pub dst_address: MacAddress, + /// The communications status + pub status: u8, + /// Security level to be used + pub security_level: u8, + /// Mode used to identify the key to be used + pub key_id_mode: u8, + /// Index of the key to be used + pub key_index: u8, + /// Originator of the key to be used + pub key_source: [u8; 8], +} + +/// MLME GTS Indication indicates that a GTS has been allocated or that a +/// previously allocated GTS has been deallocated +#[repr(C)] +pub struct GtsIndication { + /// The short address of the device that has been allocated or deallocated a GTS + pub device_address: [u8; 2], + /// The characteristics of the GTS + pub gts_characteristics: u8, + /// Security level to be used + pub security_level: u8, + /// Mode used to identify the key to be used + pub key_id_mode: u8, + /// Index of the key to be used + pub key_index: u8, + /// Originator of the key to be used + pub key_source: [u8; 8], +} + +/// MLME ORPHAN Indication which is used by the coordinator to notify the +/// application of the presence of an orphaned device +#[repr(C)] +pub struct OrphanIndication { + /// Extended address of the orphaned device + pub orphan_address: [u8; 8], + /// Originator of the key used by the originator of the received frame + pub key_source: [u8; 8], + /// Security level purportedly used by the received MAC command frame + pub security_level: u8, + /// Mode used to identify the key used by originator of received frame + pub key_id_mode: u8, + /// Index of the key used by the originator of the received frame + pub key_index: u8, +} + +/// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss +/// of synchronization with the coordinator +#[repr(C)] +pub struct SyncLossIndication { + /// The PAN identifier with which the device lost synchronization or to which it was realigned + pub pan_id: [u8; 2], + /// The reason that synchronization was lost + pub loss_reason: u8, + /// The logical channel on which the device lost synchronization or to whi + pub channel_number: u8, + /// The channel page on which the device lost synchronization or to which + pub channel_page: u8, + /// The security level used by the received MAC frame + pub security_level: u8, + /// Mode used to identify the key used by originator of received frame + pub key_id_mode: u8, + /// Index of the key used by the originator of the received frame + pub key_index: u8, + /// Originator of the key used by the originator of the received frame + pub key_source: [u8; 8], +} + +/// MLME DPS Indication which indicates the expiration of the DPSIndexDuration +/// and the resetting of the DPS values in the PHY +pub struct DpsIndication; + +#[repr(C)] +pub struct DataIndication { + /// Pointer to the set of octets forming the MSDU being indicated + pub msdu_ptr: *const u8, + /// Source addressing mode used + pub src_addr_mode: u8, + /// Source PAN ID + pub src_pan_id: [u8; 2], + /// Source address + pub src_address: MacAddress, + /// Destination addressing mode used + pub dst_addr_mode: AddressMode, + /// Destination PAN ID + pub dst_pan_id: [u8; 2], + /// Destination address + pub dst_address: MacAddress, + /// The number of octets contained in the MSDU being indicated + pub msdu_length: u8, + /// QI value measured during reception of the MPDU + pub mpdu_link_quality: u8, + /// The data sequence number of the received data frame + pub dsn: u8, + /// The time, in symbols, at which the data were received + pub time_stamp: [u8; 4], + /// The security level purportedly used by the received data frame + pub security_level: u8, + /// Mode used to identify the key used by originator of received frame + pub key_id_mode: u8, + /// The originator of the key + pub key_source: [u8; 8], + /// The index of the key + pub key_index: u8, + /// he pulse repetition value of the received PPDU + pub uwbprf: u8, + /// The preamble symbol repetitions of the UWB PHY frame + pub uwn_preamble_symbol_repetitions: u8, + /// Indicates the data rate + pub datrate: u8, + /// time units corresponding to an RMARKER at the antenna at the end of a ranging exchange, + pub ranging_received: u8, + pub ranging_counter_start: u32, + pub ranging_counter_stop: u32, + /// ime units in a message exchange over which the tracking offset was measured + pub ranging_tracking_interval: u32, + /// time units slipped or advanced by the radio tracking system + pub ranging_offset: u32, + /// The FoM characterizing the ranging measurement + pub ranging_fom: u8, + /// The Received Signal Strength Indicator measured + pub rssi: u8, +} + +/// MLME POLL Indication which will be used for indicating the Data Request +/// reception to upper layer as defined in Zigbee r22 - D.8.2 +#[repr(C)] +pub struct PollIndication { + /// addressing mode used + pub addr_mode: u8, + /// Poll requester address + pub request_address: MacAddress, +} diff --git a/embassy-stm32-wpan/src/sub/mac/mod.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs index 6a3a057f..756d7d5b 100644 --- a/embassy-stm32-wpan/src/sub/mac/mod.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -18,6 +18,7 @@ use crate::{channels, evt}; pub mod commands; mod consts; +pub mod indications; mod opcodes; pub mod responses; pub mod typedefs; diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index 7b240f37..8c30a182 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -9,6 +9,7 @@ pub trait MacResponse { /// MLME ASSOCIATE Confirm used to inform of the initiating device whether /// its request to associate was successful or unsuccessful +#[repr(C)] pub struct AssociateConfirm { /// short address allocated by the coordinator on successful association pub assoc_short_address: [u8; 2], @@ -25,6 +26,7 @@ pub struct AssociateConfirm { } /// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application. +#[repr(C)] pub struct DisassociateConfirm { /// status of the disassociation attempt pub status: u8, @@ -37,6 +39,7 @@ pub struct DisassociateConfirm { } /// MLME GET Confirm which requests information about a given PIB attribute +#[repr(C)] pub struct GetConfirm { /// The pointer to the value of the PIB attribute attempted to read pub pib_attribute_value_ptr: *const u8, @@ -50,6 +53,7 @@ pub struct GetConfirm { /// MLME GTS Confirm which eports the results of a request to allocate a new GTS /// or to deallocate an existing GTS +#[repr(C)] pub struct GtsConfirm { /// The characteristics of the GTS pub gts_characteristics: u8, @@ -58,6 +62,7 @@ pub struct GtsConfirm { } /// MLME RESET Confirm which is used to report the results of the reset operation +#[repr(C)] pub struct ResetConfirm { /// The result of the reset operation status: u8, @@ -65,12 +70,14 @@ pub struct ResetConfirm { /// MLME RX ENABLE Confirm which is used to report the results of the attempt /// to enable or disable the receiver +#[repr(C)] pub struct RxEnableConfirm { /// Result of the request to enable or disable the receiver status: u8, } /// MLME SCAN Confirm which is used to report the result of the channel scan request +#[repr(C)] pub struct ScanConfirm { /// Status of the scan request pub status: u8, @@ -93,6 +100,7 @@ pub struct ScanConfirm { } /// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute +#[repr(C)] pub struct SetConfirm { /// The result of the set operation pub status: u8, @@ -102,12 +110,14 @@ pub struct SetConfirm { /// MLME START Confirm which is used to report the results of the attempt to /// start using a new superframe configuration +#[repr(C)] pub struct StartConfirm { /// Result of the attempt to start using an updated superframe configuration pub status: u8, } /// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data +#[repr(C)] pub struct PollConfirm { /// The status of the data request pub status: u8, @@ -115,6 +125,7 @@ pub struct PollConfirm { /// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide /// channel sounding information +#[repr(C)] pub struct SoundingConfirm { /// Results of the sounding measurement sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED], @@ -122,6 +133,7 @@ pub struct SoundingConfirm { /// MLME CALIBRATE Confirm which reports the result of a request to the PHY /// to provide internal propagation path information +#[repr(C)] pub struct CalibrateConfirm { /// The status of the attempt to return sounding data pub status: u8, @@ -135,6 +147,7 @@ pub struct CalibrateConfirm { /// MCPS DATA Confirm which will be used for reporting the results of /// MAC data related requests from the application +#[repr(C)] pub struct DataConfirm { /// The handle associated with the MSDU being confirmed pub msdu_handle: u8, @@ -160,6 +173,7 @@ pub struct DataConfirm { /// MCPS PURGE Confirm which will be used by the MAC to notify the application of /// the status of its request to purge an MSDU from the transaction queue +#[repr(C)] pub struct PurgeConfirm { /// Handle associated with the MSDU requested to be purged from the transaction queue pub msdu_handle: u8, From f54e1cea90527871f65ea449e58dc57fcf7cdb37 Mon Sep 17 00:00:00 2001 From: Roy Buitenhuis Date: Wed, 12 Jul 2023 11:32:02 +0200 Subject: [PATCH 071/148] Add poll functions on UdpSocket. --- embassy-net/src/udp.rs | 47 +++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs index 36f8d06f..bd7a32f7 100644 --- a/embassy-net/src/udp.rs +++ b/embassy-net/src/udp.rs @@ -102,37 +102,42 @@ impl<'a> UdpSocket<'a> { /// /// Returns the number of bytes received and the remote endpoint. pub async fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, IpEndpoint), Error> { - poll_fn(move |cx| { - self.with_mut(|s, _| match s.recv_slice(buf) { - Ok((n, meta)) => Poll::Ready(Ok((n, meta.endpoint))), - // No data ready - Err(udp::RecvError::Exhausted) => { - s.register_recv_waker(cx.waker()); - Poll::Pending - } - }) + poll_fn(move |cx| self.poll_recv_from(buf, cx)).await + } + + pub fn poll_recv_from(&self, buf: &mut[u8], cx: Context) -> Poll> { + self.with_mut(|s, _| match s.recv_slice(buf) { + Ok((n, meta)) => Poll::Ready(Ok((n, meta.endpoint))), + // No data ready + Err(udp::RecvError::Exhausted) => { + s.register_recv_waker(cx.waker()); + Poll::Pending + } }) - .await } /// Send a datagram to the specified remote endpoint. pub async fn send_to(&self, buf: &[u8], remote_endpoint: T) -> Result<(), Error> + where + T: Into, + { + poll_fn(move |cx| self.poll_send_to(buf, remote_endpoint, cx)).await + } + + pub fn poll_send_to(&self, buf: &[u8], remote_endpoint: T, cx: Context) -> Poll> where T: Into, { let remote_endpoint = remote_endpoint.into(); - poll_fn(move |cx| { - self.with_mut(|s, _| match s.send_slice(buf, remote_endpoint) { - // Entire datagram has been sent - Ok(()) => Poll::Ready(Ok(())), - Err(udp::SendError::BufferFull) => { - s.register_send_waker(cx.waker()); - Poll::Pending - } - Err(udp::SendError::Unaddressable) => Poll::Ready(Err(Error::NoRoute)), - }) + self.with_mut(|s, _| match s.send_slice(buf, remote_endpoint) { + // Entire datagram has been sent + Ok(()) => Poll::Ready(Ok(())), + Err(udp::SendError::BufferFull) => { + s.register_send_waker(cx.waker()); + Poll::Pending + } + Err(udp::SendError::Unaddressable) => Poll::Ready(Err(Error::NoRoute)), }) - .await } /// Returns the local endpoint of the socket. From b81c14f442839de61f2217cf88e09d390d465f3d Mon Sep 17 00:00:00 2001 From: Roy Buitenhuis Date: Wed, 12 Jul 2023 11:32:02 +0200 Subject: [PATCH 072/148] Add polling fn's for send_to and recv_from in UdpSocket. --- embassy-net/src/udp.rs | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs index bd7a32f7..16f48bcb 100644 --- a/embassy-net/src/udp.rs +++ b/embassy-net/src/udp.rs @@ -3,7 +3,7 @@ use core::cell::RefCell; use core::future::poll_fn; use core::mem; -use core::task::Poll; +use core::task::{Poll, Context}; use embassy_net_driver::Driver; use smoltcp::iface::{Interface, SocketHandle}; @@ -105,7 +105,14 @@ impl<'a> UdpSocket<'a> { poll_fn(move |cx| self.poll_recv_from(buf, cx)).await } - pub fn poll_recv_from(&self, buf: &mut[u8], cx: Context) -> Poll> { + /// Receive a datagram. + /// + /// When no datagram is available, this method will return `Poll::Pending` and + /// register the current task to be notified when a datagram is received. + /// + /// When a datagram is received, this method will return `Poll::Ready` with the + /// number of bytes received and the remote endpoint. + pub fn poll_recv_from(&self, buf: &mut[u8], cx: &mut Context<'_>) -> Poll> { self.with_mut(|s, _| match s.recv_slice(buf) { Ok((n, meta)) => Poll::Ready(Ok((n, meta.endpoint))), // No data ready @@ -117,18 +124,30 @@ impl<'a> UdpSocket<'a> { } /// Send a datagram to the specified remote endpoint. + /// + /// This method will wait until the datagram has been sent. + /// + /// When the remote endpoint is not reachable, this method will return `Err(Error::NoRoute)` pub async fn send_to(&self, buf: &[u8], remote_endpoint: T) -> Result<(), Error> where T: Into, { + let remote_endpoint: IpEndpoint = remote_endpoint.into(); poll_fn(move |cx| self.poll_send_to(buf, remote_endpoint, cx)).await } - pub fn poll_send_to(&self, buf: &[u8], remote_endpoint: T, cx: Context) -> Poll> + /// Send a datagram to the specified remote endpoint. + /// + /// When the datagram has been sent, this method will return `Poll::Ready(Ok())`. + /// + /// When the socket's send buffer is full, this method will return `Poll::Pending` + /// and register the current task to be notified when the buffer has space available. + /// + /// When the remote endpoint is not reachable, this method will return `Poll::Ready(Err(Error::NoRoute))`. + pub fn poll_send_to(&self, buf: &[u8], remote_endpoint: T, cx: &mut Context<'_>) -> Poll> where T: Into, { - let remote_endpoint = remote_endpoint.into(); self.with_mut(|s, _| match s.send_slice(buf, remote_endpoint) { // Entire datagram has been sent Ok(()) => Poll::Ready(Ok(())), From f192f440187c705ce2674731c4d595dc327f08a3 Mon Sep 17 00:00:00 2001 From: Roy Buitenhuis Date: Wed, 12 Jul 2023 11:32:02 +0200 Subject: [PATCH 073/148] fmt --- embassy-net/src/udp.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs index 16f48bcb..0d97b6db 100644 --- a/embassy-net/src/udp.rs +++ b/embassy-net/src/udp.rs @@ -3,7 +3,7 @@ use core::cell::RefCell; use core::future::poll_fn; use core::mem; -use core::task::{Poll, Context}; +use core::task::{Context, Poll}; use embassy_net_driver::Driver; use smoltcp::iface::{Interface, SocketHandle}; @@ -106,13 +106,13 @@ impl<'a> UdpSocket<'a> { } /// Receive a datagram. - /// + /// /// When no datagram is available, this method will return `Poll::Pending` and /// register the current task to be notified when a datagram is received. - /// + /// /// When a datagram is received, this method will return `Poll::Ready` with the /// number of bytes received and the remote endpoint. - pub fn poll_recv_from(&self, buf: &mut[u8], cx: &mut Context<'_>) -> Poll> { + pub fn poll_recv_from(&self, buf: &mut [u8], cx: &mut Context<'_>) -> Poll> { self.with_mut(|s, _| match s.recv_slice(buf) { Ok((n, meta)) => Poll::Ready(Ok((n, meta.endpoint))), // No data ready @@ -124,9 +124,9 @@ impl<'a> UdpSocket<'a> { } /// Send a datagram to the specified remote endpoint. - /// + /// /// This method will wait until the datagram has been sent. - /// + /// /// When the remote endpoint is not reachable, this method will return `Err(Error::NoRoute)` pub async fn send_to(&self, buf: &[u8], remote_endpoint: T) -> Result<(), Error> where @@ -137,12 +137,12 @@ impl<'a> UdpSocket<'a> { } /// Send a datagram to the specified remote endpoint. - /// + /// /// When the datagram has been sent, this method will return `Poll::Ready(Ok())`. - /// + /// /// When the socket's send buffer is full, this method will return `Poll::Pending` /// and register the current task to be notified when the buffer has space available. - /// + /// /// When the remote endpoint is not reachable, this method will return `Poll::Ready(Err(Error::NoRoute))`. pub fn poll_send_to(&self, buf: &[u8], remote_endpoint: T, cx: &mut Context<'_>) -> Poll> where From 55a5e9b3a51b537b7de80221d501be423af43303 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Thu, 22 Jun 2023 22:37:24 +0200 Subject: [PATCH 074/148] RP: Add RTC example to rp2040. --- examples/rp/src/bin/rtc.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 examples/rp/src/bin/rtc.rs diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs new file mode 100644 index 00000000..a49c8f62 --- /dev/null +++ b/examples/rp/src/bin/rtc.rs @@ -0,0 +1,33 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::rtc::{DateTime, DayOfWeek, RealTimeClock}; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + info!("Hello World!"); + + let now = DateTime { + year: 2020, + month: 5, + day: 15, + day_of_week: DayOfWeek::Monday, + hour: 10, + minute: 30, + second: 50, + }; + + let rtc_result = RealTimeClock::new(p.RTC, now); + if let Ok(rtc) = rtc_result { + // In reality the delay would be much longer + Timer::after(Duration::from_millis(20000)).await; + + let _then: DateTime = rtc.now().unwrap(); + } +} From 029b156563e70e00cf0ffdf9d5ec23964e5ecc77 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Mon, 26 Jun 2023 08:48:04 +0200 Subject: [PATCH 075/148] RP: Add scratchN registers to watchdog. Add Clone and Debug to DateTime --- embassy-rp/src/rtc/datetime_no_deps.rs | 1 + embassy-rp/src/watchdog.rs | 96 ++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/embassy-rp/src/rtc/datetime_no_deps.rs b/embassy-rp/src/rtc/datetime_no_deps.rs index 92770e98..ea899c33 100644 --- a/embassy-rp/src/rtc/datetime_no_deps.rs +++ b/embassy-rp/src/rtc/datetime_no_deps.rs @@ -25,6 +25,7 @@ pub enum Error { } /// Structure containing date and time information +#[derive(Clone, Debug)] pub struct DateTime { /// 0..4095 pub year: u16, diff --git a/embassy-rp/src/watchdog.rs b/embassy-rp/src/watchdog.rs index d37795cc..7b36bb5a 100644 --- a/embassy-rp/src/watchdog.rs +++ b/embassy-rp/src/watchdog.rs @@ -107,4 +107,100 @@ impl Watchdog { w.set_trigger(true); }) } + + pub fn set_scratch0(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch0().write(|w| { + *w = value; + }) + } + + pub fn get_scratch0(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch0().read() + } + + pub fn set_scratch1(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch1().write(|w| { + *w = value; + }) + } + + pub fn get_scratch1(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch1().read() + } + + pub fn set_scratch2(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch2().write(|w| { + *w = value; + }) + } + + pub fn get_scratch2(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch2().read() + } + + pub fn set_scratch3(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch3().write(|w| { + *w = value; + }) + } + + pub fn get_scratch3(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch3().read() + } + + pub fn set_scratch4(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch4().write(|w| { + *w = value; + }) + } + + pub fn get_scratch4(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch4().read() + } + + pub fn set_scratch5(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch5().write(|w| { + *w = value; + }) + } + + pub fn get_scratch5(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch5().read() + } + + pub fn set_scratch6(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch6().write(|w| { + *w = value; + }) + } + + pub fn get_scratch6(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch6().read() + } + + pub fn set_scratch7(&mut self, value: u32) { + let watchdog = pac::WATCHDOG; + watchdog.scratch7().write(|w| { + *w = value; + }) + } + + pub fn get_scratch7(&mut self) -> u32 { + let watchdog = pac::WATCHDOG; + watchdog.scratch7().read() + } } From a93714327eb85b02c7c4a419f2a76df579258975 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Tue, 11 Jul 2023 18:41:45 +0200 Subject: [PATCH 076/148] RP: Rename Rtc to match STM32 impl. Remove setting RTC in new(). --- embassy-rp/src/rtc/mod.rs | 20 +++++++++----------- examples/rp/src/bin/rtc.rs | 14 ++++++++++---- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs index b18f12fc..90b796a9 100644 --- a/embassy-rp/src/rtc/mod.rs +++ b/embassy-rp/src/rtc/mod.rs @@ -12,26 +12,24 @@ pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; use crate::clocks::clk_rtc_freq; /// A reference to the real time clock of the system -pub struct RealTimeClock<'d, T: Instance> { +pub struct Rtc<'d, T: Instance> { inner: PeripheralRef<'d, T>, } -impl<'d, T: Instance> RealTimeClock<'d, T> { +impl<'d, T: Instance> Rtc<'d, T> { /// Create a new instance of the real time clock, with the given date as an initial value. /// /// # Errors /// /// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range. - pub fn new(inner: impl Peripheral

+ 'd, initial_date: DateTime) -> Result { + pub fn new(inner: impl Peripheral

+ 'd) -> Self { into_ref!(inner); // Set the RTC divider inner.regs().clkdiv_m1().write(|w| w.set_clkdiv_m1(clk_rtc_freq() - 1)); - let mut result = Self { inner }; - result.set_leap_year_check(true); // should be on by default, make sure this is the case. - result.set_datetime(initial_date)?; - Ok(result) + let result = Self { inner }; + result } /// Enable or disable the leap year check. The rp2040 chip will always add a Feb 29th on every year that is divisable by 4, but this may be incorrect (e.g. on century years). This function allows you to disable this check. @@ -43,7 +41,7 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { }); } - /// Checks to see if this RealTimeClock is running + /// Checks to see if this Rtc is running pub fn is_running(&self) -> bool { self.inner.regs().ctrl().read().rtc_active() } @@ -113,8 +111,8 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { /// # fn main() { } /// # #[cfg(not(feature = "chrono"))] /// # fn main() { - /// # use embassy_rp::rtc::{RealTimeClock, DateTimeFilter}; - /// # let mut real_time_clock: RealTimeClock = unsafe { core::mem::zeroed() }; + /// # use embassy_rp::rtc::{Rtc, DateTimeFilter}; + /// # let mut real_time_clock: Rtc = unsafe { core::mem::zeroed() }; /// let now = real_time_clock.now().unwrap(); /// real_time_clock.schedule_alarm( /// DateTimeFilter::default() @@ -150,7 +148,7 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { } } -/// Errors that can occur on methods on [RealTimeClock] +/// Errors that can occur on methods on [Rtc] #[derive(Clone, Debug, PartialEq, Eq)] pub enum RtcError { /// An invalid DateTime was given or stored on the hardware. diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs index a49c8f62..6300950d 100644 --- a/examples/rp/src/bin/rtc.rs +++ b/examples/rp/src/bin/rtc.rs @@ -4,7 +4,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::rtc::{DateTime, DayOfWeek, RealTimeClock}; +use embassy_rp::rtc::{DateTime, DayOfWeek, Rtc}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -23,11 +23,17 @@ async fn main(_spawner: Spawner) { second: 50, }; - let rtc_result = RealTimeClock::new(p.RTC, now); - if let Ok(rtc) = rtc_result { + let mut rtc = Rtc::new(p.RTC); + if rtc.set_datetime(now).is_ok() { // In reality the delay would be much longer Timer::after(Duration::from_millis(20000)).await; - let _then: DateTime = rtc.now().unwrap(); + if let Ok(dt) = rtc.now() { + info!( + "Now: {}-{}-{} {}:{}:{}", + dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, + ); + } } + info!("Done."); } From 466a391b52836f79fafad5780ad2eb0a07d82513 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Wed, 12 Jul 2023 14:13:19 +0200 Subject: [PATCH 077/148] RP: Add save/restore to Rtc. Example use. --- embassy-rp/src/rtc/mod.rs | 30 +++++++++++++++++++++ examples/rp/src/bin/rtc.rs | 55 +++++++++++++++++++++++--------------- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs index 90b796a9..1b33fdf8 100644 --- a/embassy-rp/src/rtc/mod.rs +++ b/embassy-rp/src/rtc/mod.rs @@ -41,6 +41,36 @@ impl<'d, T: Instance> Rtc<'d, T> { }); } + /// Set the time from internal format + pub fn restore(&mut self, ymd: rp_pac::rtc::regs::Rtc1, hms: rp_pac::rtc::regs::Rtc0) { + // disable RTC while we configure it + self.inner.regs().ctrl().modify(|w| w.set_rtc_enable(false)); + while self.inner.regs().ctrl().read().rtc_active() { + core::hint::spin_loop(); + } + + self.inner.regs().setup_0().write(|w| { + *w = rp_pac::rtc::regs::Setup0(ymd.0); + }); + self.inner.regs().setup_1().write(|w| { + *w = rp_pac::rtc::regs::Setup1(hms.0); + }); + + // Load the new datetime and re-enable RTC + self.inner.regs().ctrl().write(|w| w.set_load(true)); + self.inner.regs().ctrl().write(|w| w.set_rtc_enable(true)); + while !self.inner.regs().ctrl().read().rtc_active() { + core::hint::spin_loop(); + } + } + + /// Get the time in internal format + pub fn save(&mut self) -> (rp_pac::rtc::regs::Rtc1, rp_pac::rtc::regs::Rtc0) { + let rtc_0: rp_pac::rtc::regs::Rtc0 = self.inner.regs().rtc_0().read(); + let rtc_1 = self.inner.regs().rtc_1().read(); + (rtc_1, rtc_0) + } + /// Checks to see if this Rtc is running pub fn is_running(&self) -> bool { self.inner.regs().ctrl().read().rtc_active() diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs index 6300950d..2ddde325 100644 --- a/examples/rp/src/bin/rtc.rs +++ b/examples/rp/src/bin/rtc.rs @@ -4,6 +4,7 @@ use defmt::*; use embassy_executor::Spawner; +use embassy_rp::pac::rtc::regs::{Rtc0, Rtc1}; use embassy_rp::rtc::{DateTime, DayOfWeek, Rtc}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -11,29 +12,41 @@ use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); - info!("Hello World!"); - - let now = DateTime { - year: 2020, - month: 5, - day: 15, - day_of_week: DayOfWeek::Monday, - hour: 10, - minute: 30, - second: 50, - }; + info!("Wait for 20s"); + let mut watchdog = embassy_rp::watchdog::Watchdog::new(p.WATCHDOG); let mut rtc = Rtc::new(p.RTC); - if rtc.set_datetime(now).is_ok() { - // In reality the delay would be much longer - Timer::after(Duration::from_millis(20000)).await; - if let Ok(dt) = rtc.now() { - info!( - "Now: {}-{}-{} {}:{}:{}", - dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, - ); - } + let rtc0 = Rtc0(watchdog.get_scratch0()); + let rtc1 = Rtc1(watchdog.get_scratch1()); + if rtc1.year() >= 2020 { + rtc.restore(rtc1, rtc0); + } else { + let now = DateTime { + year: 2020, + month: 5, + day: 15, + day_of_week: DayOfWeek::Monday, + hour: 10, + minute: 30, + second: 50, + }; + rtc.set_datetime(now).unwrap(); } - info!("Done."); + + Timer::after(Duration::from_millis(20000)).await; + + if let Ok(dt) = rtc.now() { + info!( + "Now: {}-{:02}-{:02} {}:{:02}:{:02}", + dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, + ); + let (rtc1, rtc0) = rtc.save(); + watchdog.set_scratch0(rtc0.0); + watchdog.set_scratch1(rtc1.0); + } + + info!("Reboot."); + Timer::after(Duration::from_millis(200)).await; + cortex_m::peripheral::SCB::sys_reset(); } From 6d402fe3932ac04ff939379e6520322476f683dc Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Wed, 12 Jul 2023 15:16:56 +0200 Subject: [PATCH 078/148] RP: Don't reset RTC in Clock::init. Updated example. --- embassy-rp/src/clocks.rs | 2 ++ examples/rp/src/bin/rtc.rs | 26 +++++++++----------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index ddd61d22..acb21dce 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -308,6 +308,7 @@ pub(crate) unsafe fn init(config: ClockConfig) { // - QSPI (we're using it to run this code!) // - PLLs (it may be suicide if that's what's clocking us) // - USB, SYSCFG (breaks usb-to-swd on core1) + // - RTC (else there would be no more time...) let mut peris = reset::ALL_PERIPHERALS; peris.set_io_qspi(false); // peris.set_io_bank0(false); // might be suicide if we're clocked from gpin @@ -317,6 +318,7 @@ pub(crate) unsafe fn init(config: ClockConfig) { // TODO investigate if usb should be unreset here peris.set_usbctrl(false); peris.set_syscfg(false); + peris.set_rtc(false); reset::reset(peris); // Disable resus that may be enabled from previous software diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs index 2ddde325..d569f598 100644 --- a/examples/rp/src/bin/rtc.rs +++ b/examples/rp/src/bin/rtc.rs @@ -4,7 +4,6 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::pac::rtc::regs::{Rtc0, Rtc1}; use embassy_rp::rtc::{DateTime, DayOfWeek, Rtc}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -14,22 +13,18 @@ async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); info!("Wait for 20s"); - let mut watchdog = embassy_rp::watchdog::Watchdog::new(p.WATCHDOG); let mut rtc = Rtc::new(p.RTC); - let rtc0 = Rtc0(watchdog.get_scratch0()); - let rtc1 = Rtc1(watchdog.get_scratch1()); - if rtc1.year() >= 2020 { - rtc.restore(rtc1, rtc0); - } else { + if !rtc.is_running() { + info!("Start RTC"); let now = DateTime { - year: 2020, - month: 5, - day: 15, - day_of_week: DayOfWeek::Monday, - hour: 10, - minute: 30, - second: 50, + year: 2000, + month: 1, + day: 1, + day_of_week: DayOfWeek::Saturday, + hour: 0, + minute: 0, + second: 0, }; rtc.set_datetime(now).unwrap(); } @@ -41,9 +36,6 @@ async fn main(_spawner: Spawner) { "Now: {}-{:02}-{:02} {}:{:02}:{:02}", dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, ); - let (rtc1, rtc0) = rtc.save(); - watchdog.set_scratch0(rtc0.0); - watchdog.set_scratch1(rtc1.0); } info!("Reboot."); From d5a4457b5e3a95a12f249315fb1d9b6a577307f2 Mon Sep 17 00:00:00 2001 From: goueslati Date: Wed, 12 Jul 2023 15:06:56 +0100 Subject: [PATCH 079/148] parsing MAC structs --- embassy-stm32-wpan/Cargo.toml | 7 +- embassy-stm32-wpan/src/sub/mac/commands.rs | 55 +-- embassy-stm32-wpan/src/sub/mac/event.rs | 94 +++++ embassy-stm32-wpan/src/sub/mac/helpers.rs | 7 + embassy-stm32-wpan/src/sub/mac/indications.rs | 295 ++++++++++++-- embassy-stm32-wpan/src/sub/mac/macros.rs | 32 ++ embassy-stm32-wpan/src/sub/mac/mod.rs | 63 ++- embassy-stm32-wpan/src/sub/mac/opcodes.rs | 63 +++ embassy-stm32-wpan/src/sub/mac/responses.rs | 302 +++++++++++++-- embassy-stm32-wpan/src/sub/mac/typedefs.rs | 359 ++++++++++++++---- examples/stm32wb/src/bin/mac_ffd.rs | 99 ++--- examples/stm32wb/src/bin/mac_rfd.rs | 14 +- 12 files changed, 1107 insertions(+), 283 deletions(-) create mode 100644 embassy-stm32-wpan/src/sub/mac/event.rs create mode 100644 embassy-stm32-wpan/src/sub/mac/helpers.rs create mode 100644 embassy-stm32-wpan/src/sub/mac/macros.rs diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 4b5dcdd2..1325faed 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -26,13 +26,14 @@ aligned = "0.4.1" bit_field = "0.10.2" stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } stm32wb-hci = { version = "0.1.2", features = ["version-5-0"], optional = true } +bitflags = { version = "2.3.3", optional = true } [features] -default = ["stm32wb55rg", "mac", "ble"] +default = ["stm32wb55rg", "mac", "ble", "defmt"] defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] ble = ["dep:stm32wb-hci"] -mac = [] +mac = ["dep:bitflags"] stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] @@ -49,4 +50,4 @@ stm32wb55rg = [ "embassy-stm32/stm32wb55rg" ] stm32wb55vc = [ "embassy-stm32/stm32wb55vc" ] stm32wb55ve = [ "embassy-stm32/stm32wb55ve" ] stm32wb55vg = [ "embassy-stm32/stm32wb55vg" ] -stm32wb55vy = [ "embassy-stm32/stm32wb55vy" ] \ No newline at end of file +stm32wb55vy = [ "embassy-stm32/stm32wb55vy" ] diff --git a/embassy-stm32-wpan/src/sub/mac/commands.rs b/embassy-stm32-wpan/src/sub/mac/commands.rs index 4965a46e..d8a4e3ee 100644 --- a/embassy-stm32-wpan/src/sub/mac/commands.rs +++ b/embassy-stm32-wpan/src/sub/mac/commands.rs @@ -1,5 +1,8 @@ use super::opcodes::OpcodeM4ToM0; -use super::typedefs::{AddressMode, GtsCharacteristics, MacAddress, PibId}; +use super::typedefs::{ + AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, PibId, + ScanType, SecurityLevel, +}; pub trait MacCommand { const OPCODE: OpcodeM4ToM0; @@ -14,19 +17,19 @@ pub trait MacCommand { #[repr(C)] pub struct AssociateRequest { /// the logical channel on which to attempt association - pub channel_number: u8, + pub channel_number: MacChannel, /// the channel page on which to attempt association pub channel_page: u8, /// coordinator addressing mode pub coord_addr_mode: AddressMode, /// operational capabilities of the associating device - pub capability_information: u8, + pub capability_information: Capabilities, /// the identifier of the PAN with which to associate pub coord_pan_id: [u8; 2], /// the security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the originator of the key to be used pub key_source: [u8; 8], /// Coordinator address @@ -48,15 +51,15 @@ pub struct DisassociateRequest { /// the identifier of the PAN of the device pub device_pan_id: [u8; 2], /// the reason for the disassociation - pub disassociate_reason: u8, + pub disassociation_reason: DisassociationReason, /// device address pub device_address: MacAddress, /// `true` if the disassociation notification command is to be sent indirectly pub tx_indirect: bool, /// the security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the mode to be used to indetify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, /// the originator of the key to be used @@ -86,9 +89,9 @@ pub struct GtsRequest { /// the characteristics of the GTS pub characteristics: GtsCharacteristics, /// the security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, /// the originator of the key to be used @@ -147,19 +150,19 @@ impl MacCommand for RxEnableRequest { #[repr(C)] pub struct ScanRequest { /// the type of scan to be performed - pub scan_type: u8, + pub scan_type: ScanType, /// the time spent on scanning each channel pub scan_duration: u8, /// channel page on which to perform the scan pub channel_page: u8, /// security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// indicate which channels are to be scanned pub scan_channels: [u8; 4], /// originator the key to be used pub key_source: [u8; 8], /// mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// index of the key to be used pub key_index: u8, } @@ -191,7 +194,7 @@ pub struct StartRequest { /// PAN indentifier to used by the device pub pan_id: [u8; 2], /// logical channel on which to begin - pub channel_number: u8, + pub channel_number: MacChannel, /// channel page on which to begin pub channel_page: u8, /// time at which to begin transmitting beacons @@ -207,15 +210,15 @@ pub struct StartRequest { /// indicated if the coordinator realignment command is to be trasmitted pub coord_realignment: u8, /// indicated if the coordinator realignment command is to be trasmitted - pub coord_realign_security_level: u8, + pub coord_realign_security_level: SecurityLevel, /// index of the key to be used pub coord_realign_key_id_index: u8, /// originator of the key to be used pub coord_realign_key_source: [u8; 8], /// security level to be used for beacon frames - pub beacon_security_level: u8, + pub beacon_security_level: SecurityLevel, /// mode used to identify the key to be used - pub beacon_key_id_mode: u8, + pub beacon_key_id_mode: KeyIdMode, /// index of the key to be used pub beacon_key_index: u8, /// originator of the key to be used @@ -232,7 +235,7 @@ impl MacCommand for StartRequest { #[repr(C)] pub struct SyncRequest { /// the channel number on which to attempt coordinator synchronization - pub channel_number: u8, + pub channel_number: MacChannel, /// the channel page on which to attempt coordinator synchronization pub channel_page: u8, /// `true` if the MLME is to synchronize with the next beacon and attempts @@ -253,9 +256,9 @@ pub struct PollRequest { /// addressing mode of the coordinator pub coord_addr_mode: AddressMode, /// security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// index of the key to be used pub key_index: u8, /// coordinator address @@ -335,9 +338,9 @@ pub struct DataRequest { /// the pending bit transmission options for the MSDU pub indirect_tx: u8, /// the security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the mode used to indentify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, /// the originator of the key to be used @@ -381,11 +384,11 @@ pub struct AssociateResponse { /// status of the association attempt pub status: u8, /// security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the originator of the key to be used pub key_source: [u8; 8], /// the mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, } @@ -405,11 +408,11 @@ pub struct OrphanResponse { /// if the orphaned device is associated with coordinator or not pub associated_member: bool, /// security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the originator of the key to be used pub key_source: [u8; 8], /// the mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, } diff --git a/embassy-stm32-wpan/src/sub/mac/event.rs b/embassy-stm32-wpan/src/sub/mac/event.rs new file mode 100644 index 00000000..aaf96556 --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/event.rs @@ -0,0 +1,94 @@ +use super::helpers::to_u16; +use super::indications::{ + AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication, + DpsIndication, GtsIndication, OrphanIndication, PollIndication, SyncLossIndication, +}; +use super::responses::{ + AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm, + PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm, +}; +use crate::sub::mac::opcodes::OpcodeM0ToM4; + +pub trait ParseableMacEvent { + const SIZE: usize; + + fn validate(buf: &[u8]) -> Result<(), ()> { + if buf.len() < Self::SIZE { + return Err(()); + } + + Ok(()) + } + + fn try_parse(buf: &[u8]) -> Result + where + Self: Sized; +} + +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum MacEvent { + MlmeAssociateCnf(AssociateConfirm), + MlmeDisassociateCnf(DisassociateConfirm), + MlmeGetCnf(GetConfirm), + MlmeGtsCnf(GtsConfirm), + MlmeResetCnf(ResetConfirm), + MlmeRxEnableCnf(RxEnableConfirm), + MlmeScanCnf(ScanConfirm), + MlmeSetCnf(SetConfirm), + MlmeStartCnf(StartConfirm), + MlmePollCnf(PollConfirm), + MlmeDpsCnf(DpsConfirm), + MlmeSoundingCnf(SoundingConfirm), + MlmeCalibrateCnf(CalibrateConfirm), + McpsDataCnf(DataConfirm), + McpsPurgeCnf(PurgeConfirm), + MlmeAssociateInd(AssociateIndication), + MlmeDisassociateInd(DisassociateIndication), + MlmeBeaconNotifyInd(BeaconNotifyIndication), + MlmeCommStatusInd(CommStatusIndication), + MlmeGtsInd(GtsIndication), + MlmeOrphanInd(OrphanIndication), + MlmeSyncLossInd(SyncLossIndication), + MlmeDpsInd(DpsIndication), + McpsDataInd(DataIndication), + MlmePollInd(PollIndication), +} + +impl TryFrom<&[u8]> for MacEvent { + type Error = (); + + fn try_from(value: &[u8]) -> Result { + let opcode = to_u16(&value[0..2]); + let opcode = OpcodeM0ToM4::try_from(opcode)?; + + let buf = &value[2..]; + + match opcode { + OpcodeM0ToM4::MlmeAssociateCnf => Ok(Self::MlmeAssociateCnf(AssociateConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeDisassociateCnf => Ok(Self::MlmeDisassociateCnf(DisassociateConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeGetCnf => Ok(Self::MlmeGetCnf(GetConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeGtsCnf => Ok(Self::MlmeGtsCnf(GtsConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeResetCnf => Ok(Self::MlmeResetCnf(ResetConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeRxEnableCnf => Ok(Self::MlmeRxEnableCnf(RxEnableConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeScanCnf => Ok(Self::MlmeScanCnf(ScanConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeSetCnf => Ok(Self::MlmeSetCnf(SetConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeStartCnf => Ok(Self::MlmeStartCnf(StartConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmePollCnf => Ok(Self::MlmePollCnf(PollConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeDpsCnf => Ok(Self::MlmeDpsCnf(DpsConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeSoundingCnf => Ok(Self::MlmeSoundingCnf(SoundingConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeCalibrateCnf => Ok(Self::MlmeCalibrateCnf(CalibrateConfirm::try_parse(buf)?)), + OpcodeM0ToM4::McpsDataCnf => Ok(Self::McpsDataCnf(DataConfirm::try_parse(buf)?)), + OpcodeM0ToM4::McpsPurgeCnf => Ok(Self::McpsPurgeCnf(PurgeConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeAssociateInd => Ok(Self::MlmeAssociateInd(AssociateIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeDisassociateInd => Ok(Self::MlmeDisassociateInd(DisassociateIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeBeaconNotifyInd => Ok(Self::MlmeBeaconNotifyInd(BeaconNotifyIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeCommStatusInd => Ok(Self::MlmeCommStatusInd(CommStatusIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeGtsInd => Ok(Self::MlmeGtsInd(GtsIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeOrphanInd => Ok(Self::MlmeOrphanInd(OrphanIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeSyncLossInd => Ok(Self::MlmeSyncLossInd(SyncLossIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeDpsInd => Ok(Self::MlmeDpsInd(DpsIndication::try_parse(buf)?)), + OpcodeM0ToM4::McpsDataInd => Ok(Self::McpsDataInd(DataIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmePollInd => Ok(Self::MlmePollInd(PollIndication::try_parse(buf)?)), + } + } +} diff --git a/embassy-stm32-wpan/src/sub/mac/helpers.rs b/embassy-stm32-wpan/src/sub/mac/helpers.rs new file mode 100644 index 00000000..5a5bf8a8 --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/helpers.rs @@ -0,0 +1,7 @@ +pub fn to_u16(buf: &[u8]) -> u16 { + ((buf[1] as u16) << 8) | buf[0] as u16 +} + +pub fn to_u32(buf: &[u8]) -> u32 { + ((buf[0] as u32) << 0) + ((buf[1] as u32) << 8) + ((buf[2] as u32) << 16) + ((buf[3] as u32) << 24) +} diff --git a/embassy-stm32-wpan/src/sub/mac/indications.rs b/embassy-stm32-wpan/src/sub/mac/indications.rs index ebca16f7..dc5ae4c4 100644 --- a/embassy-stm32-wpan/src/sub/mac/indications.rs +++ b/embassy-stm32-wpan/src/sub/mac/indications.rs @@ -1,45 +1,84 @@ use super::consts::MAX_PENDING_ADDRESS; -use super::typedefs::{AddressMode, MacAddress, PanDescriptor}; +use super::event::ParseableMacEvent; +use super::helpers::to_u32; +use super::typedefs::{ + AddressMode, Capabilities, DisassociationReason, KeyIdMode, MacAddress, MacChannel, MacStatus, PanDescriptor, + SecurityLevel, +}; /// MLME ASSOCIATE Indication which will be used by the MAC /// to indicate the reception of an association request command -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateIndication { /// Extended address of the device requesting association pub device_address: [u8; 8], /// Operational capabilities of the device requesting association - pub capability_information: u8, + pub capability_information: Capabilities, /// Security level purportedly used by the received MAC command frame - pub security_level: u8, + pub security_level: SecurityLevel, /// The mode used to identify the key used by the originator of frame - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// Index of the key used by the originator of the received frame pub key_index: u8, /// The originator of the key used by the originator of the received frame pub key_source: [u8; 8], } +impl ParseableMacEvent for AssociateIndication { + const SIZE: usize = 20; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + device_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], + capability_information: Capabilities::from_bits(buf[8]).ok_or(())?, + security_level: SecurityLevel::try_from(buf[9])?, + key_id_mode: KeyIdMode::try_from(buf[10])?, + key_index: buf[11], + key_source: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]], + }) + } +} + /// MLME DISASSOCIATE indication which will be used to send /// disassociation indication to the application. -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DisassociateIndication { /// Extended address of the device requesting association pub device_address: [u8; 8], /// The reason for the disassociation - pub disassociate_reason: u8, + pub disassociation_reason: DisassociationReason, /// The security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// The mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// The index of the key to be used pub key_index: u8, /// The originator of the key to be used pub key_source: [u8; 8], } +impl ParseableMacEvent for DisassociateIndication { + const SIZE: usize = 20; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + device_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], + disassociation_reason: DisassociationReason::try_from(buf[8])?, + security_level: SecurityLevel::try_from(buf[9])?, + key_id_mode: KeyIdMode::try_from(buf[10])?, + key_index: buf[11], + key_source: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]], + }) + } +} + /// MLME BEACON NOTIIFY Indication which is used to send parameters contained /// within a beacon frame received by the MAC to the application -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct BeaconNotifyIndication { /// he set of octets comprising the beacon payload to be transferred /// from the MAC sublayer entity to the next higher layer @@ -56,8 +95,18 @@ pub struct BeaconNotifyIndication { pub sdu_length: u8, } +impl ParseableMacEvent for BeaconNotifyIndication { + const SIZE: usize = 12; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + todo!() + } +} + /// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CommStatusIndication { /// The 16-bit PAN identifier of the device from which the frame /// was received or to which the frame was being sent @@ -71,83 +120,190 @@ pub struct CommStatusIndication { /// Destination address pub dst_address: MacAddress, /// The communications status - pub status: u8, + pub status: MacStatus, /// Security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// Mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// Index of the key to be used pub key_index: u8, /// Originator of the key to be used pub key_source: [u8; 8], } +impl ParseableMacEvent for CommStatusIndication { + const SIZE: usize = 32; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + let src_addr_mode = AddressMode::try_from(buf[2])?; + let dst_addr_mode = AddressMode::try_from(buf[3])?; + + let src_address = match src_addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[4], buf[5]]), + AddressMode::Extended => { + MacAddress::Extended([buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]]) + } + }; + + let dst_address = match dst_addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[12], buf[13]]), + AddressMode::Extended => { + MacAddress::Extended([buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]]) + } + }; + + Ok(Self { + pan_id: [buf[0], buf[1]], + src_addr_mode, + dst_addr_mode, + src_address, + dst_address, + status: MacStatus::try_from(buf[20])?, + security_level: SecurityLevel::try_from(buf[21])?, + key_id_mode: KeyIdMode::try_from(buf[22])?, + key_index: buf[23], + key_source: [buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31]], + }) + } +} + /// MLME GTS Indication indicates that a GTS has been allocated or that a /// previously allocated GTS has been deallocated -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsIndication { /// The short address of the device that has been allocated or deallocated a GTS pub device_address: [u8; 2], /// The characteristics of the GTS pub gts_characteristics: u8, /// Security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// Mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// Index of the key to be used pub key_index: u8, /// Originator of the key to be used pub key_source: [u8; 8], } +impl ParseableMacEvent for GtsIndication { + const SIZE: usize = 16; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + device_address: [buf[0], buf[1]], + gts_characteristics: buf[2], + security_level: SecurityLevel::try_from(buf[3])?, + key_id_mode: KeyIdMode::try_from(buf[4])?, + key_index: buf[5], + // 2 byte stuffing + key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]], + }) + } +} + /// MLME ORPHAN Indication which is used by the coordinator to notify the /// application of the presence of an orphaned device -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct OrphanIndication { /// Extended address of the orphaned device pub orphan_address: [u8; 8], /// Originator of the key used by the originator of the received frame pub key_source: [u8; 8], /// Security level purportedly used by the received MAC command frame - pub security_level: u8, + pub security_level: SecurityLevel, /// Mode used to identify the key used by originator of received frame - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// Index of the key used by the originator of the received frame pub key_index: u8, } +impl ParseableMacEvent for OrphanIndication { + const SIZE: usize = 20; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + orphan_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], + key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]], + security_level: SecurityLevel::try_from(buf[16])?, + key_id_mode: KeyIdMode::try_from(buf[17])?, + key_index: buf[18], + // 1 byte stuffing + }) + } +} + /// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss /// of synchronization with the coordinator -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SyncLossIndication { /// The PAN identifier with which the device lost synchronization or to which it was realigned pub pan_id: [u8; 2], /// The reason that synchronization was lost pub loss_reason: u8, /// The logical channel on which the device lost synchronization or to whi - pub channel_number: u8, + pub channel_number: MacChannel, /// The channel page on which the device lost synchronization or to which pub channel_page: u8, /// The security level used by the received MAC frame - pub security_level: u8, + pub security_level: SecurityLevel, /// Mode used to identify the key used by originator of received frame - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// Index of the key used by the originator of the received frame pub key_index: u8, /// Originator of the key used by the originator of the received frame pub key_source: [u8; 8], } +impl ParseableMacEvent for SyncLossIndication { + const SIZE: usize = 16; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + pan_id: [buf[0], buf[1]], + loss_reason: buf[2], + channel_number: MacChannel::try_from(buf[3])?, + channel_page: buf[4], + security_level: SecurityLevel::try_from(buf[5])?, + key_id_mode: KeyIdMode::try_from(buf[6])?, + key_index: buf[7], + key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]], + }) + } +} + /// MLME DPS Indication which indicates the expiration of the DPSIndexDuration /// and the resetting of the DPS values in the PHY +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DpsIndication; -#[repr(C)] +impl ParseableMacEvent for DpsIndication { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self) + } +} + +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DataIndication { /// Pointer to the set of octets forming the MSDU being indicated pub msdu_ptr: *const u8, /// Source addressing mode used - pub src_addr_mode: u8, + pub src_addr_mode: AddressMode, /// Source PAN ID pub src_pan_id: [u8; 2], /// Source address @@ -167,9 +323,9 @@ pub struct DataIndication { /// The time, in symbols, at which the data were received pub time_stamp: [u8; 4], /// The security level purportedly used by the received data frame - pub security_level: u8, + pub security_level: SecurityLevel, /// Mode used to identify the key used by originator of received frame - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// The originator of the key pub key_source: [u8; 8], /// The index of the key @@ -194,12 +350,91 @@ pub struct DataIndication { pub rssi: u8, } +impl ParseableMacEvent for DataIndication { + const SIZE: usize = 72; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + let src_addr_mode = AddressMode::try_from(buf[4])?; + let src_address = match src_addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[7], buf[8]]), + AddressMode::Extended => { + MacAddress::Extended([buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14]]) + } + }; + + let dst_addr_mode = AddressMode::try_from(buf[15])?; + let dst_address = match dst_addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[18], buf[19]]), + AddressMode::Extended => { + MacAddress::Extended([buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], buf[24], buf[25]]) + } + }; + + Ok(Self { + msdu_ptr: to_u32(&buf[0..4]) as *const u8, + src_addr_mode, + src_pan_id: [buf[5], buf[6]], + src_address, + dst_addr_mode, + dst_pan_id: [buf[16], buf[17]], + dst_address, + msdu_length: buf[26], + mpdu_link_quality: buf[27], + dsn: buf[28], + time_stamp: [buf[29], buf[30], buf[31], buf[32]], + security_level: SecurityLevel::try_from(buf[33])?, + key_id_mode: KeyIdMode::try_from(buf[34])?, + key_source: [buf[35], buf[36], buf[37], buf[38], buf[39], buf[40], buf[41], buf[42]], + key_index: buf[43], + uwbprf: buf[44], + uwn_preamble_symbol_repetitions: buf[45], + datrate: buf[46], + ranging_received: buf[47], + ranging_counter_start: to_u32(&buf[58..52]), + ranging_counter_stop: to_u32(&buf[52..56]), + ranging_tracking_interval: to_u32(&buf[56..60]), + ranging_offset: to_u32(&buf[60..64]), + ranging_fom: buf[65], + rssi: buf[66], + }) + } +} + /// MLME POLL Indication which will be used for indicating the Data Request /// reception to upper layer as defined in Zigbee r22 - D.8.2 -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PollIndication { /// addressing mode used - pub addr_mode: u8, + pub addr_mode: AddressMode, /// Poll requester address pub request_address: MacAddress, } + +impl ParseableMacEvent for PollIndication { + const SIZE: usize = 9; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + let addr_mode = AddressMode::try_from(buf[0])?; + let request_address = match addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[1], buf[2]]), + AddressMode::Extended => { + MacAddress::Extended([buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]]) + } + }; + + Ok(Self { + addr_mode, + request_address, + }) + } +} diff --git a/embassy-stm32-wpan/src/sub/mac/macros.rs b/embassy-stm32-wpan/src/sub/mac/macros.rs new file mode 100644 index 00000000..1a988a77 --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/macros.rs @@ -0,0 +1,32 @@ +#[macro_export] +macro_rules! numeric_enum { + (#[repr($repr:ident)] + $(#$attrs:tt)* $vis:vis enum $name:ident { + $($(#$enum_attrs:tt)* $enum:ident = $constant:expr),* $(,)? + } ) => { + #[repr($repr)] + $(#$attrs)* + $vis enum $name { + $($(#$enum_attrs)* $enum = $constant),* + } + + impl ::core::convert::TryFrom<$repr> for $name { + type Error = (); + + fn try_from(value: $repr) -> ::core::result::Result { + match value { + $($constant => Ok( $name :: $enum ),)* + _ => Err(()) + } + } + } + + impl ::core::convert::From<$name> for $repr { + fn from(value: $name) -> $repr { + match value { + $($name :: $enum => $constant,)* + } + } + } + } +} diff --git a/embassy-stm32-wpan/src/sub/mac/mod.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs index 756d7d5b..0524f135 100644 --- a/embassy-stm32-wpan/src/sub/mac/mod.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -9,7 +9,8 @@ use embassy_stm32::ipcc::Ipcc; use embassy_sync::waitqueue::AtomicWaker; use self::commands::MacCommand; -use self::typedefs::MacStatus; +use self::event::MacEvent; +use self::typedefs::MacError; use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::{EvtBox, EvtPacket}; @@ -18,7 +19,10 @@ use crate::{channels, evt}; pub mod commands; mod consts; +pub mod event; +mod helpers; pub mod indications; +mod macros; mod opcodes; pub mod responses; pub mod typedefs; @@ -38,7 +42,7 @@ impl Mac { /// `HW_IPCC_MAC_802_15_4_EvtNot` /// /// This function will stall if the previous `EvtBox` has not been dropped - pub async fn read(&self) -> EvtBox { + pub async fn tl_read(&self) -> EvtBox { // Wait for the last event box to be dropped poll_fn(|cx| { MAC_WAKER.register(cx.waker()); @@ -62,33 +66,20 @@ impl Mac { } /// `HW_IPCC_MAC_802_15_4_CmdEvtNot` - pub async fn write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { - self.write(opcode, payload).await; + pub async fn tl_write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { + self.tl_write(opcode, payload).await; Ipcc::flush(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL).await; unsafe { let p_event_packet = MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket; let p_mac_rsp_evt = &((*p_event_packet).evt_serial.evt.payload) as *const u8; - let evt_serial = (MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket) - .read_volatile() - .evt_serial; - let kind = (evt_serial).kind; - let evt_code = evt_serial.evt.evt_code; - let payload_len = evt_serial.evt.payload_len; - let payload = evt_serial.evt.payload; - - debug!( - "evt kind {} evt_code {} len {} payload {}", - kind, evt_code, payload_len, payload - ); - ptr::read_volatile(p_mac_rsp_evt) } } /// `TL_MAC_802_15_4_SendCmd` - pub async fn write(&self, opcode: u16, payload: &[u8]) { + pub async fn tl_write(&self, opcode: u16, payload: &[u8]) { Ipcc::send(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL, || unsafe { CmdPacket::write_into( MAC_802_15_4_CMD_BUFFER.as_mut_ptr(), @@ -98,37 +89,31 @@ impl Mac { ); }) .await; - - unsafe { - let typ = MAC_802_15_4_CMD_BUFFER.as_ptr().read_volatile().cmdserial.ty; - let cmd_code = MAC_802_15_4_CMD_BUFFER.as_ptr().read_volatile().cmdserial.cmd.cmd_code; - let payload_len = MAC_802_15_4_CMD_BUFFER - .as_ptr() - .read_volatile() - .cmdserial - .cmd - .payload_len; - let payload = MAC_802_15_4_CMD_BUFFER.as_ptr().read_volatile().cmdserial.cmd.payload; - - debug!( - "serial type {} cmd_code {} len {} payload {}", - typ, cmd_code, payload_len, payload - ); - } } - pub async fn send_command(&self, cmd: T) -> Result + pub async fn send_command(&self, cmd: T) -> Result<(), MacError> where T: MacCommand, { let mut payload = [0u8; MAX_PACKET_SIZE]; cmd.copy_into_slice(&mut payload); - debug!("sending {:#x}", payload[..T::SIZE]); + let response = self + .tl_write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]) + .await; - let response = self.write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]).await; + if response == 0x00 { + Ok(()) + } else { + Err(MacError::from(response)) + } + } - MacStatus::try_from(response) + pub async fn read(&self) -> Result { + let evt_box = self.tl_read().await; + let payload = evt_box.payload(); + + MacEvent::try_from(payload) } } diff --git a/embassy-stm32-wpan/src/sub/mac/opcodes.rs b/embassy-stm32-wpan/src/sub/mac/opcodes.rs index 511b7815..c9a07d6a 100644 --- a/embassy-stm32-wpan/src/sub/mac/opcodes.rs +++ b/embassy-stm32-wpan/src/sub/mac/opcodes.rs @@ -25,3 +25,66 @@ pub enum OpcodeM4ToM0 { McpsDataReq = opcode(0x10), McpsPurgeReq = opcode(0x11), } + +pub enum OpcodeM0ToM4 { + MlmeAssociateCnf = 0x00, + MlmeDisassociateCnf, + MlmeGetCnf, + MlmeGtsCnf, + MlmeResetCnf, + MlmeRxEnableCnf, + MlmeScanCnf, + MlmeSetCnf, + MlmeStartCnf, + MlmePollCnf, + MlmeDpsCnf, + MlmeSoundingCnf, + MlmeCalibrateCnf, + McpsDataCnf, + McpsPurgeCnf, + MlmeAssociateInd, + MlmeDisassociateInd, + MlmeBeaconNotifyInd, + MlmeCommStatusInd, + MlmeGtsInd, + MlmeOrphanInd, + MlmeSyncLossInd, + MlmeDpsInd, + McpsDataInd, + MlmePollInd, +} + +impl TryFrom for OpcodeM0ToM4 { + type Error = (); + + fn try_from(value: u16) -> Result { + match value { + 0 => Ok(Self::MlmeAssociateCnf), + 1 => Ok(Self::MlmeDisassociateCnf), + 2 => Ok(Self::MlmeGetCnf), + 3 => Ok(Self::MlmeGtsCnf), + 4 => Ok(Self::MlmeResetCnf), + 5 => Ok(Self::MlmeRxEnableCnf), + 6 => Ok(Self::MlmeScanCnf), + 7 => Ok(Self::MlmeSetCnf), + 8 => Ok(Self::MlmeStartCnf), + 9 => Ok(Self::MlmePollCnf), + 10 => Ok(Self::MlmeDpsCnf), + 11 => Ok(Self::MlmeSoundingCnf), + 12 => Ok(Self::MlmeCalibrateCnf), + 13 => Ok(Self::McpsDataCnf), + 14 => Ok(Self::McpsPurgeCnf), + 15 => Ok(Self::MlmeAssociateInd), + 16 => Ok(Self::MlmeDisassociateInd), + 17 => Ok(Self::MlmeBeaconNotifyInd), + 18 => Ok(Self::MlmeCommStatusInd), + 19 => Ok(Self::MlmeGtsInd), + 20 => Ok(Self::MlmeOrphanInd), + 21 => Ok(Self::MlmeSyncLossInd), + 22 => Ok(Self::MlmeDpsInd), + 23 => Ok(Self::McpsDataInd), + 24 => Ok(Self::MlmePollInd), + _ => Err(()), + } + } +} diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index 8c30a182..ce2ca2fb 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -1,35 +1,50 @@ use super::consts::{MAX_ED_SCAN_RESULTS_SUPPORTED, MAX_PAN_DESC_SUPPORTED, MAX_SOUNDING_LIST_SUPPORTED}; -use super::typedefs::{AddressMode, MacAddress, PanDescriptor}; - -pub trait MacResponse { - const SIZE: usize; - - fn parse(buf: &[u8]) -> Self; -} +use super::event::ParseableMacEvent; +use super::helpers::to_u32; +use super::typedefs::{ + AddressMode, AssociationStatus, KeyIdMode, MacAddress, MacStatus, PanDescriptor, PibId, ScanType, SecurityLevel, +}; /// MLME ASSOCIATE Confirm used to inform of the initiating device whether /// its request to associate was successful or unsuccessful -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateConfirm { /// short address allocated by the coordinator on successful association pub assoc_short_address: [u8; 2], /// status of the association request - pub status: u8, + pub status: AssociationStatus, /// security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the originator of the key to be used pub key_source: [u8; 8], /// the mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, } +impl ParseableMacEvent for AssociateConfirm { + const SIZE: usize = 16; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + assoc_short_address: [buf[0], buf[1]], + status: AssociationStatus::try_from(buf[2])?, + security_level: SecurityLevel::try_from(buf[3])?, + key_source: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], + key_id_mode: KeyIdMode::try_from(buf[12])?, + key_index: buf[13], + }) + } +} + /// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application. -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DisassociateConfirm { /// status of the disassociation attempt - pub status: u8, + pub status: MacStatus, /// device addressing mode used pub device_addr_mode: AddressMode, /// the identifier of the PAN of the device @@ -38,51 +53,130 @@ pub struct DisassociateConfirm { pub device_address: MacAddress, } +impl ParseableMacEvent for DisassociateConfirm { + const SIZE: usize = 12; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + let device_addr_mode = AddressMode::try_from(buf[1])?; + let device_address = match device_addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[4], buf[5]]), + AddressMode::Extended => { + MacAddress::Extended([buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]]) + } + }; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + device_addr_mode, + device_pan_id: [buf[2], buf[3]], + device_address, + }) + } +} + /// MLME GET Confirm which requests information about a given PIB attribute -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GetConfirm { /// The pointer to the value of the PIB attribute attempted to read pub pib_attribute_value_ptr: *const u8, /// Status of the GET attempt - pub status: u8, + pub status: MacStatus, /// The name of the PIB attribute attempted to read - pub pib_attribute: u8, + pub pib_attribute: PibId, /// The lenght of the PIB attribute Value return pub pib_attribute_value_len: u8, } +impl ParseableMacEvent for GetConfirm { + const SIZE: usize = 8; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + let address = to_u32(&buf[0..4]); + + Ok(Self { + pib_attribute_value_ptr: address as *const u8, + status: MacStatus::try_from(buf[4])?, + pib_attribute: PibId::try_from(buf[5])?, + pib_attribute_value_len: buf[6], + }) + } +} + /// MLME GTS Confirm which eports the results of a request to allocate a new GTS /// or to deallocate an existing GTS -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsConfirm { /// The characteristics of the GTS pub gts_characteristics: u8, /// The status of the GTS reques - pub status: u8, + pub status: MacStatus, +} + +impl ParseableMacEvent for GtsConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + gts_characteristics: buf[0], + status: MacStatus::try_from(buf[1])?, + }) + } } /// MLME RESET Confirm which is used to report the results of the reset operation -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ResetConfirm { /// The result of the reset operation - status: u8, + status: MacStatus, +} + +impl ParseableMacEvent for ResetConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + }) + } } /// MLME RX ENABLE Confirm which is used to report the results of the attempt /// to enable or disable the receiver -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct RxEnableConfirm { /// Result of the request to enable or disable the receiver - status: u8, + status: MacStatus, +} + +impl ParseableMacEvent for RxEnableConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + }) + } } /// MLME SCAN Confirm which is used to report the result of the channel scan request -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ScanConfirm { /// Status of the scan request - pub status: u8, + pub status: MacStatus, /// The type of scan performed - pub scan_type: u8, + pub scan_type: ScanType, /// Channel page on which the scan was performed pub channel_page: u8, /// Channels given in the request which were not scanned @@ -99,44 +193,124 @@ pub struct ScanConfirm { pub uwb_energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED], } +impl ParseableMacEvent for ScanConfirm { + const SIZE: usize = 9; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + todo!() + } +} + /// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SetConfirm { /// The result of the set operation - pub status: u8, + pub status: MacStatus, /// The name of the PIB attribute that was written - pub pin_attribute: u8, + pub pin_attribute: PibId, +} + +impl ParseableMacEvent for SetConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + pin_attribute: PibId::try_from(buf[1])?, + }) + } } /// MLME START Confirm which is used to report the results of the attempt to /// start using a new superframe configuration -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct StartConfirm { /// Result of the attempt to start using an updated superframe configuration - pub status: u8, + pub status: MacStatus, +} + +impl ParseableMacEvent for StartConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + debug!("{:#x}", buf); + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + }) + } } /// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PollConfirm { /// The status of the data request - pub status: u8, + pub status: MacStatus, +} + +impl ParseableMacEvent for PollConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + }) + } +} + +/// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct DpsConfirm { + /// The status of the DPS request + pub status: MacStatus, +} + +impl ParseableMacEvent for DpsConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + }) + } } /// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide /// channel sounding information -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SoundingConfirm { /// Results of the sounding measurement sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED], } +impl ParseableMacEvent for SoundingConfirm { + const SIZE: usize = 1; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + let mut sounding_list = [0u8; MAX_SOUNDING_LIST_SUPPORTED]; + sounding_list[..buf.len()].copy_from_slice(buf); + + Ok(Self { sounding_list }) + } +} + /// MLME CALIBRATE Confirm which reports the result of a request to the PHY /// to provide internal propagation path information -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CalibrateConfirm { /// The status of the attempt to return sounding data - pub status: u8, + pub status: MacStatus, /// A count of the propagation time from the ranging counter /// to the transmit antenna pub cal_tx_rmaker_offset: u32, @@ -145,18 +319,33 @@ pub struct CalibrateConfirm { pub cal_rx_rmaker_offset: u32, } +impl ParseableMacEvent for CalibrateConfirm { + const SIZE: usize = 12; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + // 3 byte stuffing + cal_tx_rmaker_offset: to_u32(&buf[4..8]), + cal_rx_rmaker_offset: to_u32(&buf[8..12]), + }) + } +} + /// MCPS DATA Confirm which will be used for reporting the results of /// MAC data related requests from the application -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DataConfirm { /// The handle associated with the MSDU being confirmed pub msdu_handle: u8, /// The time, in symbols, at which the data were transmitted - pub a_time_stamp: [u8; 4], + pub time_stamp: [u8; 4], /// ranging status pub ranging_received: u8, /// The status of the last MSDU transmission - pub status: u8, + pub status: MacStatus, /// time units corresponding to an RMARKER at the antenna at /// the beginning of a ranging exchange pub ranging_counter_start: u32, @@ -171,12 +360,45 @@ pub struct DataConfirm { pub ranging_fom: u8, } +impl ParseableMacEvent for DataConfirm { + const SIZE: usize = 28; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + msdu_handle: buf[0], + time_stamp: [buf[1], buf[2], buf[3], buf[4]], + ranging_received: buf[5], + status: MacStatus::try_from(buf[6])?, + ranging_counter_start: to_u32(&buf[7..11]), + ranging_counter_stop: to_u32(&buf[11..15]), + ranging_tracking_interval: to_u32(&buf[15..19]), + ranging_offset: to_u32(&buf[19..23]), + ranging_fom: buf[24], + }) + } +} + /// MCPS PURGE Confirm which will be used by the MAC to notify the application of /// the status of its request to purge an MSDU from the transaction queue -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PurgeConfirm { /// Handle associated with the MSDU requested to be purged from the transaction queue pub msdu_handle: u8, /// The status of the request - pub status: u8, + pub status: MacStatus, +} + +impl ParseableMacEvent for PurgeConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + msdu_handle: buf[0], + status: MacStatus::try_from(buf[1])?, + }) + } } diff --git a/embassy-stm32-wpan/src/sub/mac/typedefs.rs b/embassy-stm32-wpan/src/sub/mac/typedefs.rs index 7f0dd75c..fe79b3a7 100644 --- a/embassy-stm32-wpan/src/sub/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/sub/mac/typedefs.rs @@ -1,6 +1,8 @@ +use crate::numeric_enum; + +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum MacStatus { - Success = 0x00, +pub enum MacError { Error = 0x01, NotImplemented = 0x02, NotSupported = 0x03, @@ -8,88 +10,115 @@ pub enum MacStatus { Undefined = 0x05, } -impl TryFrom for MacStatus { - type Error = (); - - fn try_from(value: u8) -> Result>::Error> { +impl From for MacError { + fn from(value: u8) -> Self { match value { - 0x00 => Ok(Self::Success), - 0x01 => Ok(Self::Error), - 0x02 => Ok(Self::NotImplemented), - 0x03 => Ok(Self::NotSupported), - 0x04 => Ok(Self::HardwareNotSupported), - 0x05 => Ok(Self::Undefined), - _ => Err(()), + 0x01 => Self::Error, + 0x02 => Self::NotImplemented, + 0x03 => Self::NotSupported, + 0x04 => Self::HardwareNotSupported, + 0x05 => Self::Undefined, + _ => Self::Undefined, } } } -/// this enum contains all the MAC PIB Ids -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum PibId { - // PHY - CurrentChannel = 0x00, - ChannelsSupported = 0x01, - TransmitPower = 0x02, - CCAMode = 0x03, - CurrentPage = 0x04, - MaxFrameDuration = 0x05, - SHRDuration = 0x06, - SymbolsPerOctet = 0x07, - - // MAC - AckWaitDuration = 0x40, - AssociationPermit = 0x41, - AutoRequest = 0x42, - BeaconPayload = 0x45, - BeaconPayloadLength = 0x46, - BeaconOrder = 0x47, - Bsn = 0x49, - CoordExtendedAdddress = 0x4A, - CoordShortAddress = 0x4B, - Dsn = 0x4C, - MaxFrameTotalWaitTime = 0x58, - MaxFrameRetries = 0x59, - PanId = 0x50, - ResponseWaitTime = 0x5A, - RxOnWhenIdle = 0x52, - SecurityEnabled = 0x5D, - ShortAddress = 0x53, - SuperframeOrder = 0x54, - TimestampSupported = 0x5C, - TransactionPersistenceTime = 0x55, - MaxBe = 0x57, - LifsPeriod = 0x5E, - SifsPeriod = 0x5F, - MaxCsmaBackoffs = 0x4E, - MinBe = 0x4F, - PanCoordinator = 0x10, - AssocPanCoordinator = 0x11, - ExtendedAddress = 0x6F, - AclEntryDescriptor = 0x70, - AclEntryDescriptorSize = 0x71, - DefaultSecurity = 0x72, - DefaultSecurityMaterialLength = 0x73, - DefaultSecurityMaterial = 0x74, - DefaultSecuritySuite = 0x75, - SecurityMode = 0x76, - CurrentAclEntries = 0x80, - DefaultSecurityExtendedAddress = 0x81, - AssociatedPanCoordinator = 0x56, - PromiscuousMode = 0x51, +numeric_enum! { + #[repr(u8)] + #[derive(Debug)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum MacStatus { + Success = 0x00, + Error = 0x01, + NotImplemented = 0x02, + NotSupported = 0x03, + HardwareNotSupported = 0x04, + Undefined = 0x05, + } } -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum AddressMode { - NoAddress = 0x00, - Reserved = 0x01, - Short = 0x02, - Extended = 0x03, +numeric_enum! { + #[repr(u8)] + /// this enum contains all the MAC PIB Ids + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum PibId { + // PHY + CurrentChannel = 0x00, + ChannelsSupported = 0x01, + TransmitPower = 0x02, + CCAMode = 0x03, + CurrentPage = 0x04, + MaxFrameDuration = 0x05, + SHRDuration = 0x06, + SymbolsPerOctet = 0x07, + + // MAC + AckWaitDuration = 0x40, + AssociationPermit = 0x41, + AutoRequest = 0x42, + BeaconPayload = 0x45, + BeaconPayloadLength = 0x46, + BeaconOrder = 0x47, + Bsn = 0x49, + CoordExtendedAdddress = 0x4A, + CoordShortAddress = 0x4B, + Dsn = 0x4C, + MaxFrameTotalWaitTime = 0x58, + MaxFrameRetries = 0x59, + PanId = 0x50, + ResponseWaitTime = 0x5A, + RxOnWhenIdle = 0x52, + SecurityEnabled = 0x5D, + ShortAddress = 0x53, + SuperframeOrder = 0x54, + TimestampSupported = 0x5C, + TransactionPersistenceTime = 0x55, + MaxBe = 0x57, + LifsPeriod = 0x5E, + SifsPeriod = 0x5F, + MaxCsmaBackoffs = 0x4E, + MinBe = 0x4F, + PanCoordinator = 0x10, + AssocPanCoordinator = 0x11, + ExtendedAddress = 0x6F, + AclEntryDescriptor = 0x70, + AclEntryDescriptorSize = 0x71, + DefaultSecurity = 0x72, + DefaultSecurityMaterialLength = 0x73, + DefaultSecurityMaterial = 0x74, + DefaultSecuritySuite = 0x75, + SecurityMode = 0x76, + CurrentAclEntries = 0x80, + DefaultSecurityExtendedAddress = 0x81, + AssociatedPanCoordinator = 0x56, + PromiscuousMode = 0x51, + } } -pub union MacAddress { - pub short: [u8; 2], - pub extended: [u8; 8], +numeric_enum! { + #[repr(u8)] + #[derive(Default, Clone, Copy)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum AddressMode { + #[default] + NoAddress = 0x00, + Reserved = 0x01, + Short = 0x02, + Extended = 0x03, +} +} + +#[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum MacAddress { + Short([u8; 2]), + Extended([u8; 8]), +} + +impl Default for MacAddress { + fn default() -> Self { + Self::Short([0, 0]) + } } pub struct GtsCharacteristics { @@ -98,13 +127,15 @@ pub struct GtsCharacteristics { /// MAC PAN Descriptor which contains the network details of the device from /// which the beacon is received +#[derive(Default, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PanDescriptor { /// PAN identifier of the coordinator - pub a_coord_pan_id: [u8; 2], + pub coord_pan_id: [u8; 2], /// Coordinator addressing mode pub coord_addr_mode: AddressMode, /// The current logical channel occupied by the network - pub logical_channel: u8, + pub logical_channel: MacChannel, /// Coordinator address pub coord_addr: MacAddress, /// The current channel page occupied by the network @@ -112,13 +143,179 @@ pub struct PanDescriptor { /// PAN coordinator is accepting GTS requests or not pub gts_permit: bool, /// Superframe specification as specified in the received beacon frame - pub a_superframe_spec: [u8; 2], + pub superframe_spec: [u8; 2], /// The time at which the beacon frame was received, in symbols - pub a_time_stamp: [u8; 4], + pub time_stamp: [u8; 4], /// The LQI at which the network beacon was received pub link_quality: u8, /// Security level purportedly used by the received beacon frame pub security_level: u8, - /// Byte Stuffing to keep 32 bit alignment - pub a_stuffing: [u8; 2], +} + +impl TryFrom<&[u8]> for PanDescriptor { + type Error = (); + + fn try_from(buf: &[u8]) -> Result { + const SIZE: usize = 24; + if buf.len() < SIZE { + return Err(()); + } + + let coord_addr_mode = AddressMode::try_from(buf[2])?; + let coord_addr = match coord_addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[4], buf[5]]), + AddressMode::Extended => { + MacAddress::Extended([buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]]) + } + }; + + Ok(Self { + coord_pan_id: [buf[0], buf[1]], + coord_addr_mode, + logical_channel: MacChannel::try_from(buf[3])?, + coord_addr, + channel_page: buf[12], + gts_permit: buf[13] != 0, + superframe_spec: [buf[14], buf[15]], + time_stamp: [buf[16], buf[17], buf[18], buf[19]], + link_quality: buf[20], + security_level: buf[21], + // 2 byte stuffing + }) + } +} + +numeric_enum! { + #[repr(u8)] + #[derive(Default, Clone, Copy)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + /// Building wireless applications with STM32WB series MCUs - Application note 13.10.3 + pub enum MacChannel { + Channel11 = 0x0B, + Channel12 = 0x0C, + Channel13 = 0x0D, + Channel14 = 0x0E, + Channel15 = 0x0F, + #[default] + Channel16 = 0x10, + Channel17 = 0x11, + Channel18 = 0x12, + Channel19 = 0x13, + Channel20 = 0x14, + Channel21 = 0x15, + Channel22 = 0x16, + Channel23 = 0x17, + Channel24 = 0x18, + Channel25 = 0x19, + Channel26 = 0x1A, + } +} + +#[cfg(not(feature = "defmt"))] +bitflags::bitflags! { + pub struct Capabilities: u8 { + /// 1 if the device is capabaleof becoming a PAN coordinator + const IS_COORDINATOR_CAPABLE = 0b00000001; + /// 1 if the device is an FFD, 0 if it is an RFD + const IS_FFD = 0b00000010; + /// 1 if the device is receiving power from mains, 0 if it is battery-powered + const IS_MAINS_POWERED = 0b00000100; + /// 1 if the device does not disable its receiver to conserver power during idle periods + const RECEIVER_ON_WHEN_IDLE = 0b00001000; + // 0b00010000 reserved + // 0b00100000 reserved + /// 1 if the device is capable of sending and receiving secured MAC frames + const IS_SECURE = 0b01000000; + /// 1 if the device wishes the coordinator to allocate a short address as a result of the association + const ALLOCATE_ADDRESS = 0b10000000; + } +} + +#[cfg(feature = "defmt")] +defmt::bitflags! { + pub struct Capabilities: u8 { + /// 1 if the device is capabaleof becoming a PAN coordinator + const IS_COORDINATOR_CAPABLE = 0b00000001; + /// 1 if the device is an FFD, 0 if it is an RFD + const IS_FFD = 0b00000010; + /// 1 if the device is receiving power from mains, 0 if it is battery-powered + const IS_MAINS_POWERED = 0b00000100; + /// 1 if the device does not disable its receiver to conserver power during idle periods + const RECEIVER_ON_WHEN_IDLE = 0b00001000; + // 0b00010000 reserved + // 0b00100000 reserved + /// 1 if the device is capable of sending and receiving secured MAC frames + const IS_SECURE = 0b01000000; + /// 1 if the device wishes the coordinator to allocate a short address as a result of the association + const ALLOCATE_ADDRESS = 0b10000000; + } +} + +numeric_enum! { + #[repr(u8)] + #[derive(Default)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum KeyIdMode { + #[default] + /// the key is determined implicitly from the originator and recipient(s) of the frame + Implicite = 0x00, + /// the key is determined explicitly using a 1 bytes key source and a 1 byte key index + Explicite1Byte = 0x01, + /// the key is determined explicitly using a 4 bytes key source and a 1 byte key index + Explicite4Byte = 0x02, + /// the key is determined explicitly using a 8 bytes key source and a 1 byte key index + Explicite8Byte = 0x03, + } +} + +numeric_enum! { + #[repr(u8)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum AssociationStatus { + /// Association successful + Success = 0x00, + /// PAN at capacity + PanAtCapacity = 0x01, + /// PAN access denied + PanAccessDenied = 0x02 + } +} + +numeric_enum! { + #[repr(u8)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum DisassociationReason { + /// The coordinator wishes the device to leave the PAN. + CoordRequested = 0x01, + /// The device wishes to leave the PAN. + DeviceRequested = 0x02, + } +} + +numeric_enum! { + #[repr(u8)] + #[derive(Default)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum SecurityLevel { + /// MAC Unsecured Mode Security + #[default] + Unsecure = 0x00, + /// MAC ACL Mode Security + AclMode = 0x01, + /// MAC Secured Mode Security + Secured = 0x02, + } +} + +numeric_enum! { + #[repr(u8)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum ScanType { + EdScan = 0x00, + Active = 0x01, + Passive = 0x02, + Orphan = 0x03 + } } diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 4100d1ac..18b29362 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -7,7 +7,7 @@ use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; use embassy_stm32_wpan::sub::mac::commands::{ResetRequest, SetRequest, StartRequest}; -use embassy_stm32_wpan::sub::mac::typedefs::PibId; +use embassy_stm32_wpan::sub::mac::typedefs::{MacChannel, PibId}; use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -65,109 +65,92 @@ async fn main(spawner: Spawner) { info!("initialized mac: {}", result); info!("resetting"); - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(ResetRequest { set_default_pib: true }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); info!("setting extended address"); let extended_address: u64 = 0xACDE480000000001; - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(SetRequest { pib_attribute_ptr: &extended_address as *const _ as *const u8, pib_attribute: PibId::ExtendedAddress, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); info!("setting short address"); let short_address: u16 = 0x1122; - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(SetRequest { pib_attribute_ptr: &short_address as *const _ as *const u8, pib_attribute: PibId::ShortAddress, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); info!("setting association permit"); let association_permit: bool = true; - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(SetRequest { pib_attribute_ptr: &association_permit as *const _ as *const u8, pib_attribute: PibId::AssociationPermit, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); info!("setting TX power"); let transmit_power: i8 = 2; - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(SetRequest { pib_attribute_ptr: &transmit_power as *const _ as *const u8, pib_attribute: PibId::TransmitPower, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); info!("starting FFD device"); - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(StartRequest { - channel_number: 16, + channel_number: MacChannel::Channel16, beacon_order: 0x0F, superframe_order: 0x0F, pan_coordinator: true, battery_life_extension: false, ..Default::default() }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); info!("setting RX on when idle"); let rx_on_while_idle: bool = true; - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(SetRequest { pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, pib_attribute: PibId::RxOnWhenIdle, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); - // info!("association request"); - // mbox.mac_subsystem - // .send_command(AssociateRequest { - // channel_number: 16, - // channel_page: 0, - // coord_addr_mode: 2, - // coord_address: MacAddress { short: [0x22, 0x11] }, - // capability_information: 0x80, - // coord_pan_id: [0xAA, 0x1A], - // security_level: 0, - - // key_id_mode: 0, - // key_index: 0, - // key_source: [0; 8], - // }) - // .await; - // info!("reading"); - // let result = mbox.mac_subsystem.read().await; - // info!("{}", result.payload()); - - // - // info!("starting ble..."); - // mbox.ble_subsystem.t_write(0x0c, &[]).await; - // - // info!("waiting for ble..."); - // let ble_event = mbox.ble_subsystem.tl_read().await; - // - // info!("ble event: {}", ble_event.payload()); + loop { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); + } info!("Test OK"); cortex_m::asm::bkpt(); diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index 938fe754..8042a370 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -7,7 +7,9 @@ use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, ResetRequest, SetRequest, StartRequest}; -use embassy_stm32_wpan::sub::mac::typedefs::{AddressMode, MacAddress, PibId}; +use embassy_stm32_wpan::sub::mac::typedefs::{ + AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PibId, SecurityLevel, +}; use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -86,14 +88,14 @@ async fn main(spawner: Spawner) { let response = mbox .mac_subsystem .send_command(AssociateRequest { - channel_number: 16, + channel_number: MacChannel::Channel16, channel_page: 0, coord_addr_mode: AddressMode::Short, - coord_address: MacAddress { short: [0x22, 0x11] }, - capability_information: 0x80, + coord_address: MacAddress::Short([0x22, 0x11]), + capability_information: Capabilities::ALLOCATE_ADDRESS, coord_pan_id: [0xAA, 0x1A], - security_level: 0x00, - key_id_mode: 0, + security_level: SecurityLevel::Unsecure, + key_id_mode: KeyIdMode::Implicite, key_source: [0; 8], key_index: 0, }) From ff2daaff679ab79c856164d19b1bd15c7526991f Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Wed, 12 Jul 2023 16:41:35 +0200 Subject: [PATCH 080/148] RP: Watchdog scratch set/get with index: usize. --- embassy-rp/src/watchdog.rs | 116 +++++++++---------------------------- 1 file changed, 26 insertions(+), 90 deletions(-) diff --git a/embassy-rp/src/watchdog.rs b/embassy-rp/src/watchdog.rs index 7b36bb5a..f1e986ec 100644 --- a/embassy-rp/src/watchdog.rs +++ b/embassy-rp/src/watchdog.rs @@ -108,99 +108,35 @@ impl Watchdog { }) } - pub fn set_scratch0(&mut self, value: u32) { + /// Store data in scratch register + pub fn set_scratch(&mut self, index: usize, value: u32) { let watchdog = pac::WATCHDOG; - watchdog.scratch0().write(|w| { - *w = value; - }) + match index { + 0 => watchdog.scratch0().write(|w| *w = value), + 1 => watchdog.scratch1().write(|w| *w = value), + 2 => watchdog.scratch2().write(|w| *w = value), + 3 => watchdog.scratch3().write(|w| *w = value), + 4 => watchdog.scratch4().write(|w| *w = value), + 5 => watchdog.scratch5().write(|w| *w = value), + 6 => watchdog.scratch6().write(|w| *w = value), + 7 => watchdog.scratch7().write(|w| *w = value), + _ => panic!("Invalid watchdog scratch index"), + } } - pub fn get_scratch0(&mut self) -> u32 { + /// Read data from scratch register + pub fn get_scratch(&mut self, index: usize) -> u32 { let watchdog = pac::WATCHDOG; - watchdog.scratch0().read() - } - - pub fn set_scratch1(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch1().write(|w| { - *w = value; - }) - } - - pub fn get_scratch1(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch1().read() - } - - pub fn set_scratch2(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch2().write(|w| { - *w = value; - }) - } - - pub fn get_scratch2(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch2().read() - } - - pub fn set_scratch3(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch3().write(|w| { - *w = value; - }) - } - - pub fn get_scratch3(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch3().read() - } - - pub fn set_scratch4(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch4().write(|w| { - *w = value; - }) - } - - pub fn get_scratch4(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch4().read() - } - - pub fn set_scratch5(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch5().write(|w| { - *w = value; - }) - } - - pub fn get_scratch5(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch5().read() - } - - pub fn set_scratch6(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch6().write(|w| { - *w = value; - }) - } - - pub fn get_scratch6(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch6().read() - } - - pub fn set_scratch7(&mut self, value: u32) { - let watchdog = pac::WATCHDOG; - watchdog.scratch7().write(|w| { - *w = value; - }) - } - - pub fn get_scratch7(&mut self) -> u32 { - let watchdog = pac::WATCHDOG; - watchdog.scratch7().read() + match index { + 0 => watchdog.scratch0().read(), + 1 => watchdog.scratch1().read(), + 2 => watchdog.scratch2().read(), + 3 => watchdog.scratch3().read(), + 4 => watchdog.scratch4().read(), + 5 => watchdog.scratch5().read(), + 6 => watchdog.scratch6().read(), + 7 => watchdog.scratch7().read(), + _ => panic!("Invalid watchdog scratch index"), + } } } From a2501bd5c1004362368d962b206b6de8f4962837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Wed, 12 Jul 2023 16:52:52 +0200 Subject: [PATCH 081/148] Allow clearing finished task from timer queue --- embassy-executor/src/raw/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index bd0cff26..f3760f58 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -165,6 +165,9 @@ impl TaskStorage { Poll::Ready(_) => { this.future.drop_in_place(); this.raw.state.fetch_and(!STATE_SPAWNED, Ordering::AcqRel); + + #[cfg(feature = "integrated-timers")] + this.raw.expires_at.set(Instant::MAX); } Poll::Pending => {} } From eccd2ecebf01753e70705a6ca1e21bc83b2c204c Mon Sep 17 00:00:00 2001 From: goueslati Date: Wed, 12 Jul 2023 16:49:37 +0100 Subject: [PATCH 082/148] change MacAddress to a union instead of an enum --- embassy-stm32-wpan/src/sub/mac/commands.rs | 20 +++- embassy-stm32-wpan/src/sub/mac/indications.rs | 70 ++++++++------ embassy-stm32-wpan/src/sub/mac/mod.rs | 4 +- embassy-stm32-wpan/src/sub/mac/responses.rs | 17 ++-- embassy-stm32-wpan/src/sub/mac/typedefs.rs | 43 ++++++--- examples/stm32wb/src/bin/mac_ffd.rs | 18 ++-- examples/stm32wb/src/bin/mac_rfd.rs | 92 ++++++++++++------- 7 files changed, 168 insertions(+), 96 deletions(-) diff --git a/embassy-stm32-wpan/src/sub/mac/commands.rs b/embassy-stm32-wpan/src/sub/mac/commands.rs index d8a4e3ee..7ccf1002 100644 --- a/embassy-stm32-wpan/src/sub/mac/commands.rs +++ b/embassy-stm32-wpan/src/sub/mac/commands.rs @@ -9,12 +9,13 @@ pub trait MacCommand { const SIZE: usize; fn copy_into_slice(&self, buf: &mut [u8]) { - unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, 8) }; + unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, Self::SIZE) }; } } /// MLME ASSOCIATE Request used to request an association #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateRequest { /// the logical channel on which to attempt association pub channel_number: MacChannel, @@ -45,6 +46,7 @@ impl MacCommand for AssociateRequest { /// MLME DISASSOCIATE Request sed to request a disassociation #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DisassociateRequest { /// device addressing mode used pub device_addr_mode: AddressMode, @@ -73,6 +75,7 @@ impl MacCommand for DisassociateRequest { /// MLME GET Request used to request a PIB value #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GetRequest { /// the name of the PIB attribute to read pub pib_attribute: PibId, @@ -85,6 +88,7 @@ impl MacCommand for GetRequest { /// MLME GTS Request used to request and maintain GTSs #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsRequest { /// the characteristics of the GTS pub characteristics: GtsCharacteristics, @@ -104,6 +108,7 @@ impl MacCommand for GtsRequest { } #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ResetRequest { /// MAC PIB attributes are set to their default values or not during reset pub set_default_pib: bool, @@ -117,6 +122,7 @@ impl MacCommand for ResetRequest { /// MLME RX ENABLE Request used to request that the receiver is either enabled /// for a finite period of time or disabled #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct RxEnableRequest { /// the request operation can be deferred or not pub defer_permit: bool, @@ -148,6 +154,7 @@ impl MacCommand for RxEnableRequest { /// MLME SCAN Request used to initiate a channel scan over a given list of channels #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ScanRequest { /// the type of scan to be performed pub scan_type: ScanType, @@ -174,6 +181,7 @@ impl MacCommand for ScanRequest { /// MLME SET Request used to attempt to write the given value to the indicated PIB attribute #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SetRequest { /// the pointer to the value of the PIB attribute to set pub pib_attribute_ptr: *const u8, @@ -190,6 +198,7 @@ impl MacCommand for SetRequest { /// configuration #[derive(Default)] #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct StartRequest { /// PAN indentifier to used by the device pub pan_id: [u8; 2], @@ -233,6 +242,7 @@ impl MacCommand for StartRequest { /// MLME SYNC Request used to synchronize with the coordinator by acquiring and, if /// specified, tracking its beacons #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SyncRequest { /// the channel number on which to attempt coordinator synchronization pub channel_number: MacChannel, @@ -252,6 +262,7 @@ impl MacCommand for SyncRequest { /// MLME POLL Request propmts the device to request data from the coordinator #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PollRequest { /// addressing mode of the coordinator pub coord_addr_mode: AddressMode, @@ -277,6 +288,7 @@ impl MacCommand for PollRequest { /// MLME DPS Request allows the next higher layer to request that the PHY utilize a /// given pair of preamble codes for a single use pending expiration of the DPSIndexDuration #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DpsRequest { /// the index value for the transmitter tx_dps_index: u8, @@ -295,6 +307,7 @@ impl MacCommand for DpsRequest { /// MLME SOUNDING request primitive which is used by the next higher layer to request that /// the PHY respond with channel sounding information #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SoundingRequest; impl MacCommand for SoundingRequest { @@ -305,6 +318,7 @@ impl MacCommand for SoundingRequest { /// MLME CALIBRATE request primitive which used to obtain the results of a ranging /// calibration request from an RDEV #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CalibrateRequest; impl MacCommand for CalibrateRequest { @@ -314,6 +328,7 @@ impl MacCommand for CalibrateRequest { /// MCPS DATA Request used for MAC data related requests from the application #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DataRequest { /// the handle assocated with the MSDU to be transmitted pub msdu_ptr: *const u8, @@ -362,6 +377,7 @@ impl MacCommand for DataRequest { /// for MCPS PURGE Request used to purge an MSDU from the transaction queue #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PurgeRequest { /// the handle associated with the MSDU to be purged from the transaction /// queue @@ -375,6 +391,7 @@ impl MacCommand for PurgeRequest { /// MLME ASSOCIATE Response used to initiate a response to an MLME-ASSOCIATE.indication #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateResponse { /// extended address of the device requesting association pub device_address: [u8; 8], @@ -400,6 +417,7 @@ impl MacCommand for AssociateResponse { /// MLME ORPHAN Response used to respond to the MLME ORPHAN Indication #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct OrphanResponse { /// extended address of the orphaned device pub orphan_address: [u8; 8], diff --git a/embassy-stm32-wpan/src/sub/mac/indications.rs b/embassy-stm32-wpan/src/sub/mac/indications.rs index dc5ae4c4..4695f24e 100644 --- a/embassy-stm32-wpan/src/sub/mac/indications.rs +++ b/embassy-stm32-wpan/src/sub/mac/indications.rs @@ -141,21 +141,25 @@ impl ParseableMacEvent for CommStatusIndication { let dst_addr_mode = AddressMode::try_from(buf[3])?; let src_address = match src_addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[4], buf[5]]), - AddressMode::Extended => { - MacAddress::Extended([buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[4], buf[5]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], + }, }; let dst_address = match dst_addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[12], buf[13]]), - AddressMode::Extended => { - MacAddress::Extended([buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[12], buf[13]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]], + }, }; Ok(Self { @@ -358,22 +362,26 @@ impl ParseableMacEvent for DataIndication { let src_addr_mode = AddressMode::try_from(buf[4])?; let src_address = match src_addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[7], buf[8]]), - AddressMode::Extended => { - MacAddress::Extended([buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[7], buf[8]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14]], + }, }; let dst_addr_mode = AddressMode::try_from(buf[15])?; let dst_address = match dst_addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[18], buf[19]]), - AddressMode::Extended => { - MacAddress::Extended([buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], buf[24], buf[25]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[18], buf[19]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], buf[24], buf[25]], + }, }; Ok(Self { @@ -424,12 +432,14 @@ impl ParseableMacEvent for PollIndication { let addr_mode = AddressMode::try_from(buf[0])?; let request_address = match addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[1], buf[2]]), - AddressMode::Extended => { - MacAddress::Extended([buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[1], buf[2]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]], + }, }; Ok(Self { diff --git a/embassy-stm32-wpan/src/sub/mac/mod.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs index 0524f135..26358bf8 100644 --- a/embassy-stm32-wpan/src/sub/mac/mod.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -91,13 +91,15 @@ impl Mac { .await; } - pub async fn send_command(&self, cmd: T) -> Result<(), MacError> + pub async fn send_command(&self, cmd: &T) -> Result<(), MacError> where T: MacCommand, { let mut payload = [0u8; MAX_PACKET_SIZE]; cmd.copy_into_slice(&mut payload); + debug!("sending {}", &payload[..T::SIZE]); + let response = self .tl_write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]) .await; diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index ce2ca2fb..37271ec2 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -27,6 +27,8 @@ impl ParseableMacEvent for AssociateConfirm { const SIZE: usize = 16; fn try_parse(buf: &[u8]) -> Result { + debug!("{}", buf); + Self::validate(buf)?; Ok(Self { @@ -61,12 +63,14 @@ impl ParseableMacEvent for DisassociateConfirm { let device_addr_mode = AddressMode::try_from(buf[1])?; let device_address = match device_addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[4], buf[5]]), - AddressMode::Extended => { - MacAddress::Extended([buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[4], buf[5]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], + }, }; Ok(Self { @@ -238,7 +242,6 @@ impl ParseableMacEvent for StartConfirm { fn try_parse(buf: &[u8]) -> Result { Self::validate(buf)?; - debug!("{:#x}", buf); Ok(Self { status: MacStatus::try_from(buf[0])?, diff --git a/embassy-stm32-wpan/src/sub/mac/typedefs.rs b/embassy-stm32-wpan/src/sub/mac/typedefs.rs index fe79b3a7..1a4c30cb 100644 --- a/embassy-stm32-wpan/src/sub/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/sub/mac/typedefs.rs @@ -109,18 +109,32 @@ numeric_enum! { } #[derive(Clone, Copy)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum MacAddress { - Short([u8; 2]), - Extended([u8; 8]), +pub union MacAddress { + pub short: [u8; 2], + pub extended: [u8; 8], +} + +#[cfg(feature = "defmt")] +impl defmt::Format for MacAddress { + fn format(&self, fmt: defmt::Formatter) { + unsafe { + defmt::write!( + fmt, + "MacAddress {{ short: {}, extended: {} }}", + self.short, + self.extended + ) + } + } } impl Default for MacAddress { fn default() -> Self { - Self::Short([0, 0]) + Self { short: [0, 0] } } } +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsCharacteristics { pub fields: u8, } @@ -163,12 +177,14 @@ impl TryFrom<&[u8]> for PanDescriptor { let coord_addr_mode = AddressMode::try_from(buf[2])?; let coord_addr = match coord_addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[4], buf[5]]), - AddressMode::Extended => { - MacAddress::Extended([buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[4], buf[5]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], + }, }; Ok(Self { @@ -255,7 +271,7 @@ defmt::bitflags! { numeric_enum! { #[repr(u8)] - #[derive(Default)] + #[derive(Default, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum KeyIdMode { #[default] @@ -285,6 +301,7 @@ numeric_enum! { numeric_enum! { #[repr(u8)] + #[derive(Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DisassociationReason { /// The coordinator wishes the device to leave the PAN. @@ -296,7 +313,7 @@ numeric_enum! { numeric_enum! { #[repr(u8)] - #[derive(Default)] + #[derive(Default, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SecurityLevel { /// MAC Unsecured Mode Security diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 18b29362..4e2578a2 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -66,7 +66,7 @@ async fn main(spawner: Spawner) { info!("resetting"); mbox.mac_subsystem - .send_command(ResetRequest { set_default_pib: true }) + .send_command(&ResetRequest { set_default_pib: true }) .await .unwrap(); let evt = mbox.mac_subsystem.read().await; @@ -75,7 +75,7 @@ async fn main(spawner: Spawner) { info!("setting extended address"); let extended_address: u64 = 0xACDE480000000001; mbox.mac_subsystem - .send_command(SetRequest { + .send_command(&SetRequest { pib_attribute_ptr: &extended_address as *const _ as *const u8, pib_attribute: PibId::ExtendedAddress, }) @@ -87,7 +87,7 @@ async fn main(spawner: Spawner) { info!("setting short address"); let short_address: u16 = 0x1122; mbox.mac_subsystem - .send_command(SetRequest { + .send_command(&SetRequest { pib_attribute_ptr: &short_address as *const _ as *const u8, pib_attribute: PibId::ShortAddress, }) @@ -99,7 +99,7 @@ async fn main(spawner: Spawner) { info!("setting association permit"); let association_permit: bool = true; mbox.mac_subsystem - .send_command(SetRequest { + .send_command(&SetRequest { pib_attribute_ptr: &association_permit as *const _ as *const u8, pib_attribute: PibId::AssociationPermit, }) @@ -111,7 +111,7 @@ async fn main(spawner: Spawner) { info!("setting TX power"); let transmit_power: i8 = 2; mbox.mac_subsystem - .send_command(SetRequest { + .send_command(&SetRequest { pib_attribute_ptr: &transmit_power as *const _ as *const u8, pib_attribute: PibId::TransmitPower, }) @@ -122,7 +122,8 @@ async fn main(spawner: Spawner) { info!("starting FFD device"); mbox.mac_subsystem - .send_command(StartRequest { + .send_command(&StartRequest { + pan_id: [0xAA, 0x1A], channel_number: MacChannel::Channel16, beacon_order: 0x0F, superframe_order: 0x0F, @@ -138,7 +139,7 @@ async fn main(spawner: Spawner) { info!("setting RX on when idle"); let rx_on_while_idle: bool = true; mbox.mac_subsystem - .send_command(SetRequest { + .send_command(&SetRequest { pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, pib_attribute: PibId::RxOnWhenIdle, }) @@ -151,7 +152,4 @@ async fn main(spawner: Spawner) { let evt = mbox.mac_subsystem.read().await; defmt::info!("{:#x}", evt); } - - info!("Test OK"); - cortex_m::asm::bkpt(); } diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index 8042a370..e5f8d54c 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -6,7 +6,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, ResetRequest, SetRequest, StartRequest}; +use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, GetRequest, ResetRequest, SetRequest}; +use embassy_stm32_wpan::sub::mac::event::MacEvent; use embassy_stm32_wpan::sub::mac::typedefs::{ AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PibId, SecurityLevel, }; @@ -67,52 +68,75 @@ async fn main(spawner: Spawner) { info!("initialized mac: {}", result); info!("resetting"); - let response = mbox - .mac_subsystem - .send_command(ResetRequest { set_default_pib: true }) - .await; - info!("{}", response); + mbox.mac_subsystem + .send_command(&ResetRequest { set_default_pib: true }) + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); info!("setting extended address"); let extended_address: u64 = 0xACDE480000000002; - let response = mbox - .mac_subsystem - .send_command(SetRequest { + mbox.mac_subsystem + .send_command(&SetRequest { pib_attribute_ptr: &extended_address as *const _ as *const u8, pib_attribute: PibId::ExtendedAddress, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + + info!("getting extended address"); + mbox.mac_subsystem + .send_command(&GetRequest { + pib_attribute: PibId::ExtendedAddress, + }) + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + + if let Ok(MacEvent::MlmeGetCnf(evt)) = evt { + if evt.pib_attribute_value_len == 8 { + let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; + + info!("value {:#x}", value) + } + } info!("assocation request"); - let response = mbox - .mac_subsystem - .send_command(AssociateRequest { - channel_number: MacChannel::Channel16, - channel_page: 0, - coord_addr_mode: AddressMode::Short, - coord_address: MacAddress::Short([0x22, 0x11]), - capability_information: Capabilities::ALLOCATE_ADDRESS, - coord_pan_id: [0xAA, 0x1A], - security_level: SecurityLevel::Unsecure, - key_id_mode: KeyIdMode::Implicite, - key_source: [0; 8], - key_index: 0, - }) - .await; - info!("{}", response); + let a = AssociateRequest { + channel_number: MacChannel::Channel16, + channel_page: 0, + coord_addr_mode: AddressMode::Short, + coord_address: MacAddress { short: [34, 17] }, + capability_information: Capabilities::ALLOCATE_ADDRESS, + coord_pan_id: [0xAA, 0x1A], + security_level: SecurityLevel::Unsecure, + key_id_mode: KeyIdMode::Implicite, + key_source: [0; 8], + key_index: 152, + }; + info!("{}", a); + mbox.mac_subsystem.send_command(&a).await.unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); info!("setting short address"); let short: u64 = 0xACDE480000000002; - let response = mbox - .mac_subsystem - .send_command(SetRequest { + mbox.mac_subsystem + .send_command(&SetRequest { pib_attribute_ptr: &short as *const _ as *const u8, pib_attribute: PibId::ShortAddress, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); - info!("Test OK"); - cortex_m::asm::bkpt(); + loop { + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + } } From dff9bd9711205fd4cd5a91384072ab6aa2335d18 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 12 Jul 2023 18:30:43 +0200 Subject: [PATCH 083/148] Remove trivial to remove uses of atomic-polyfill. --- embassy-stm32/src/dma/dma.rs | 3 +-- embassy-stm32/src/flash/asynch.rs | 2 +- embassy-stm32/src/flash/common.rs | 2 +- embassy-stm32/src/flash/f0.rs | 3 +-- embassy-stm32/src/flash/f3.rs | 3 +-- embassy-stm32/src/flash/f4.rs | 3 +-- embassy-stm32/src/flash/h7.rs | 3 +-- embassy-stm32/src/flash/l.rs | 3 +-- embassy-stm32/src/ipcc.rs | 3 +-- embassy-stm32/src/usb_otg/usb.rs | 2 +- embassy-time/src/driver_std.rs | 2 +- embassy-time/src/driver_wasm.rs | 2 +- 12 files changed, 12 insertions(+), 19 deletions(-) diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index 8abe541d..58d438af 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs @@ -1,10 +1,9 @@ use core::future::Future; use core::marker::PhantomData; use core::pin::Pin; -use core::sync::atomic::{fence, Ordering}; +use core::sync::atomic::{fence, AtomicUsize, Ordering}; use core::task::{Context, Poll, Waker}; -use atomic_polyfill::AtomicUsize; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index 70a5ded6..f175349c 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; +use core::sync::atomic::{fence, Ordering}; -use atomic_polyfill::{fence, Ordering}; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::into_ref; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index c6cdc574..2a374733 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; +use core::sync::atomic::{fence, Ordering}; -use atomic_polyfill::{fence, Ordering}; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; use stm32_metapac::FLASH_BASE; diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index 02bd4cc1..ec8343e7 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs @@ -1,7 +1,6 @@ use core::convert::TryInto; use core::ptr::write_volatile; - -use atomic_polyfill::{fence, Ordering}; +use core::sync::atomic::{fence, Ordering}; use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs index b093a783..40335d64 100644 --- a/embassy-stm32/src/flash/f3.rs +++ b/embassy-stm32/src/flash/f3.rs @@ -1,7 +1,6 @@ use core::convert::TryInto; use core::ptr::write_volatile; - -use atomic_polyfill::{fence, Ordering}; +use core::sync::atomic::{fence, Ordering}; use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 242d9927..4cb39e03 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -1,8 +1,7 @@ use core::convert::TryInto; use core::ptr::write_volatile; -use core::sync::atomic::{fence, Ordering}; +use core::sync::atomic::{fence, AtomicBool, Ordering}; -use atomic_polyfill::AtomicBool; use embassy_sync::waitqueue::AtomicWaker; use pac::flash::regs::Sr; use pac::FLASH_SIZE; diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index 9baf059e..bf17b5b1 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs @@ -1,7 +1,6 @@ use core::convert::TryInto; use core::ptr::write_volatile; - -use atomic_polyfill::{fence, Ordering}; +use core::sync::atomic::{fence, Ordering}; use super::{FlashRegion, FlashSector, BANK1_REGION, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs index deefd05e..243c8b51 100644 --- a/embassy-stm32/src/flash/l.rs +++ b/embassy-stm32/src/flash/l.rs @@ -1,6 +1,5 @@ use core::ptr::write_volatile; - -use atomic_polyfill::{fence, Ordering}; +use core::sync::atomic::{fence, Ordering}; use super::{FlashRegion, FlashSector, FLASH_REGIONS, WRITE_SIZE}; use crate::flash::Error; diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs index 37f840c7..a24cba9f 100644 --- a/embassy-stm32/src/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs @@ -1,8 +1,7 @@ use core::future::poll_fn; +use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use atomic_polyfill::{compiler_fence, Ordering}; - use self::sealed::Instance; use crate::interrupt; use crate::interrupt::typelevel::Interrupt; diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs index d0284746..fd0e22ad 100644 --- a/embassy-stm32/src/usb_otg/usb.rs +++ b/embassy-stm32/src/usb_otg/usb.rs @@ -1,8 +1,8 @@ use core::cell::UnsafeCell; use core::marker::PhantomData; +use core::sync::atomic::{AtomicBool, AtomicU16, Ordering}; use core::task::Poll; -use atomic_polyfill::{AtomicBool, AtomicU16, Ordering}; use embassy_hal_common::{into_ref, Peripheral}; use embassy_sync::waitqueue::AtomicWaker; use embassy_usb_driver::{ diff --git a/embassy-time/src/driver_std.rs b/embassy-time/src/driver_std.rs index 9f8c57b5..32db47a3 100644 --- a/embassy-time/src/driver_std.rs +++ b/embassy-time/src/driver_std.rs @@ -1,10 +1,10 @@ +use core::sync::atomic::{AtomicU8, Ordering}; use std::cell::{RefCell, UnsafeCell}; use std::mem::MaybeUninit; use std::sync::{Condvar, Mutex, Once}; use std::time::{Duration as StdDuration, Instant as StdInstant}; use std::{mem, ptr, thread}; -use atomic_polyfill::{AtomicU8, Ordering}; use critical_section::Mutex as CsMutex; use crate::driver::{AlarmHandle, Driver}; diff --git a/embassy-time/src/driver_wasm.rs b/embassy-time/src/driver_wasm.rs index 63d04989..0f672dc7 100644 --- a/embassy-time/src/driver_wasm.rs +++ b/embassy-time/src/driver_wasm.rs @@ -1,9 +1,9 @@ +use core::sync::atomic::{AtomicU8, Ordering}; use std::cell::UnsafeCell; use std::mem::MaybeUninit; use std::ptr; use std::sync::{Mutex, Once}; -use atomic_polyfill::{AtomicU8, Ordering}; use wasm_bindgen::prelude::*; use wasm_timer::Instant as StdInstant; From 588c0479f5dacd21e8654463eb3ca3d847d5dcd9 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Thu, 13 Jul 2023 11:16:11 +0200 Subject: [PATCH 084/148] Add descriptions to all RP2040 examples. Some need hardware that was not specified. --- examples/rp/src/bin/adc.rs | 5 ++++- examples/rp/src/bin/blinky.rs | 4 ++++ examples/rp/src/bin/button.rs | 4 ++++ examples/rp/src/bin/flash.rs | 2 ++ examples/rp/src/bin/gpio_async.rs | 6 ++++-- examples/rp/src/bin/gpout.rs | 4 ++++ examples/rp/src/bin/i2c_async.rs | 5 +++++ examples/rp/src/bin/i2c_blocking.rs | 5 +++++ examples/rp/src/bin/lora_lorawan.rs | 1 + examples/rp/src/bin/lora_p2p_receive.rs | 1 + examples/rp/src/bin/lora_p2p_send.rs | 1 + examples/rp/src/bin/lora_p2p_send_multicore.rs | 1 + examples/rp/src/bin/multicore.rs | 4 ++++ examples/rp/src/bin/pio_async.rs | 11 ++++++++++- examples/rp/src/bin/pio_dma.rs | 2 ++ examples/rp/src/bin/pio_hd44780.rs | 3 +++ examples/rp/src/bin/pio_ws2812.rs | 3 +++ examples/rp/src/bin/pwm.rs | 4 ++++ examples/rp/src/bin/rtc.rs | 2 ++ examples/rp/src/bin/spi.rs | 4 ++++ examples/rp/src/bin/spi_async.rs | 3 +++ examples/rp/src/bin/spi_display.rs | 5 +++++ examples/rp/src/bin/uart.rs | 6 ++++++ examples/rp/src/bin/uart_buffered_split.rs | 6 ++++++ examples/rp/src/bin/uart_unidir.rs | 6 +++++- examples/rp/src/bin/usb_ethernet.rs | 4 ++++ examples/rp/src/bin/usb_logger.rs | 4 ++++ examples/rp/src/bin/usb_serial.rs | 4 ++++ examples/rp/src/bin/watchdog.rs | 4 ++++ examples/rp/src/bin/wifi_ap_tcp_server.rs | 3 +++ examples/rp/src/bin/wifi_blinky.rs | 4 ++++ examples/rp/src/bin/wifi_scan.rs | 3 +++ examples/rp/src/bin/wifi_tcp_server.rs | 3 +++ 33 files changed, 122 insertions(+), 5 deletions(-) diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index 65069cde..c0cbe017 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs @@ -1,3 +1,6 @@ +//! This example test the ADC (Analog to Digital Conversion) of the RS2040 pin 26, 27 and 28. +//! It also reads the temperature sensor in the chip. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] @@ -38,5 +41,5 @@ async fn main(_spawner: Spawner) { fn convert_to_celsius(raw_temp: u16) -> f32 { // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet - 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721 as f32 + 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721 } diff --git a/examples/rp/src/bin/blinky.rs b/examples/rp/src/bin/blinky.rs index 7aa36a19..295b000f 100644 --- a/examples/rp/src/bin/blinky.rs +++ b/examples/rp/src/bin/blinky.rs @@ -1,3 +1,7 @@ +//! This example test the RP Pico on board LED. +//! +//! It does not work with the RP Pico W board. See wifi_blinky.rs. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/button.rs b/examples/rp/src/bin/button.rs index 0d246c09..d7aa8941 100644 --- a/examples/rp/src/bin/button.rs +++ b/examples/rp/src/bin/button.rs @@ -1,3 +1,7 @@ +//! This example uses the RP Pico on board LED to test input pin 28. This is not the button on the board. +//! +//! It does not work with the RP Pico W board. Use wifi_blinky.rs and add input pin. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/flash.rs b/examples/rp/src/bin/flash.rs index 19076150..4c4982ac 100644 --- a/examples/rp/src/bin/flash.rs +++ b/examples/rp/src/bin/flash.rs @@ -1,3 +1,5 @@ +//! This example test the flash connected to the RP2040 chip. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/gpio_async.rs b/examples/rp/src/bin/gpio_async.rs index 52d13a9d..bf58044d 100644 --- a/examples/rp/src/bin/gpio_async.rs +++ b/examples/rp/src/bin/gpio_async.rs @@ -1,3 +1,7 @@ +//! This example shows how async gpio can be used with a RP2040. +//! +//! The LED on the RP Pico W board is connected differently. See wifi_blinky.rs. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] @@ -9,8 +13,6 @@ use embassy_time::{Duration, Timer}; use gpio::{Input, Level, Output, Pull}; use {defmt_rtt as _, panic_probe as _}; -/// This example shows how async gpio can be used with a RP2040. -/// /// It requires an external signal to be manually triggered on PIN 16. For /// example, this could be accomplished using an external power source with a /// button so that it is possible to toggle the signal from low to high. diff --git a/examples/rp/src/bin/gpout.rs b/examples/rp/src/bin/gpout.rs index 64461fc5..0a3b5fa9 100644 --- a/examples/rp/src/bin/gpout.rs +++ b/examples/rp/src/bin/gpout.rs @@ -1,3 +1,7 @@ +//! This example shows how GPOUT (General purpose clock outputs) can toggle a output pin. +//! +//! The LED on the RP Pico W board is connected differently. Add a LED and resistor to another pin. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/i2c_async.rs b/examples/rp/src/bin/i2c_async.rs index cf3cf742..93224bc4 100644 --- a/examples/rp/src/bin/i2c_async.rs +++ b/examples/rp/src/bin/i2c_async.rs @@ -1,3 +1,8 @@ +//! This example shows how to communicate asynchronous using i2c with external chips. +//! +//! Example written for the [`MCP23017 16-Bit I2C I/O Expander with Serial Interface`] chip. +//! (https://www.microchip.com/en-us/product/mcp23017) + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/i2c_blocking.rs b/examples/rp/src/bin/i2c_blocking.rs index 7623e33c..1c8c2039 100644 --- a/examples/rp/src/bin/i2c_blocking.rs +++ b/examples/rp/src/bin/i2c_blocking.rs @@ -1,3 +1,8 @@ +//! This example shows how to communicate using i2c with external chips. +//! +//! Example written for the [`MCP23017 16-Bit I2C I/O Expander with Serial Interface`] chip. +//! (https://www.microchip.com/en-us/product/mcp23017) + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/lora_lorawan.rs b/examples/rp/src/bin/lora_lorawan.rs index a9c84bf9..d631fafa 100644 --- a/examples/rp/src/bin/lora_lorawan.rs +++ b/examples/rp/src/bin/lora_lorawan.rs @@ -1,5 +1,6 @@ //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. //! It demonstrates LoRaWAN join functionality. + #![no_std] #![no_main] #![macro_use] diff --git a/examples/rp/src/bin/lora_p2p_receive.rs b/examples/rp/src/bin/lora_p2p_receive.rs index 25041920..396d669d 100644 --- a/examples/rp/src/bin/lora_p2p_receive.rs +++ b/examples/rp/src/bin/lora_p2p_receive.rs @@ -1,5 +1,6 @@ //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. //! It demonstrates LORA P2P receive functionality in conjunction with the lora_p2p_send example. + #![no_std] #![no_main] #![macro_use] diff --git a/examples/rp/src/bin/lora_p2p_send.rs b/examples/rp/src/bin/lora_p2p_send.rs index 3a0544b1..a0f70fa5 100644 --- a/examples/rp/src/bin/lora_p2p_send.rs +++ b/examples/rp/src/bin/lora_p2p_send.rs @@ -1,5 +1,6 @@ //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. //! It demonstrates LORA P2P send functionality. + #![no_std] #![no_main] #![macro_use] diff --git a/examples/rp/src/bin/lora_p2p_send_multicore.rs b/examples/rp/src/bin/lora_p2p_send_multicore.rs index eef2f7a5..89a62818 100644 --- a/examples/rp/src/bin/lora_p2p_send_multicore.rs +++ b/examples/rp/src/bin/lora_p2p_send_multicore.rs @@ -1,5 +1,6 @@ //! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio. //! It demonstrates LORA P2P send functionality using the second core, with data provided by the first core. + #![no_std] #![no_main] #![macro_use] diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs index 57278dd6..893b724b 100644 --- a/examples/rp/src/bin/multicore.rs +++ b/examples/rp/src/bin/multicore.rs @@ -1,3 +1,7 @@ +//! This example shows how to send messages between the two cores in the RP2040 chip. +//! +//! The LED on the RP Pico W board is connected differently. See wifi_blinky.rs. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 69034c92..c001d644 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -1,3 +1,5 @@ +//! This example shows powerful PIO module in the RP2040 chip. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] @@ -54,7 +56,14 @@ fn setup_pio_task_sm1<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, // Setupm sm1 // Read 0b10101 repeatedly until ISR is full - let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); + let prg = pio_proc::pio_asm!( + // + ".origin 8", + "set x, 0x15", + ".wrap_target", + "in x, 5 [31]", + ".wrap", + ); let relocated = RelocatedProgram::new(&prg.program); let mut cfg = Config::default(); diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 80c96355..9ab72e1f 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -1,3 +1,5 @@ +//! This example shows powerful PIO module in the RP2040 chip. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 0a4514a6..8aedd24b 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -1,3 +1,6 @@ +//! This example shows powerful PIO module in the RP2040 chip to communicate with a HD44780 display. +//! See (https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs index 4a111e7a..3de2bd48 100644 --- a/examples/rp/src/bin/pio_ws2812.rs +++ b/examples/rp/src/bin/pio_ws2812.rs @@ -1,3 +1,6 @@ +//! This example shows powerful PIO module in the RP2040 chip to communicate with WS2812 LED modules. +//! See (https://www.sparkfun.com/categories/tags/ws2812) + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/pwm.rs b/examples/rp/src/bin/pwm.rs index 2b3d5d97..9d919287 100644 --- a/examples/rp/src/bin/pwm.rs +++ b/examples/rp/src/bin/pwm.rs @@ -1,3 +1,7 @@ +//! This example shows how to use PWM (Pulse Width Modulation) in the RP2040 chip. +//! +//! The LED on the RP Pico W board is connected differently. Add a LED and resistor to another pin. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/rtc.rs b/examples/rp/src/bin/rtc.rs index d569f598..15aa8243 100644 --- a/examples/rp/src/bin/rtc.rs +++ b/examples/rp/src/bin/rtc.rs @@ -1,3 +1,5 @@ +//! This example shows how to use RTC (Real Time Clock) in the RP2040 chip. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/spi.rs b/examples/rp/src/bin/spi.rs index a830a17a..602348f7 100644 --- a/examples/rp/src/bin/spi.rs +++ b/examples/rp/src/bin/spi.rs @@ -1,3 +1,7 @@ +//! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip. +//! +//! Example for resistive touch sensor in Waveshare Pico-ResTouch + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/spi_async.rs b/examples/rp/src/bin/spi_async.rs index 671a9caa..328074e8 100644 --- a/examples/rp/src/bin/spi_async.rs +++ b/examples/rp/src/bin/spi_async.rs @@ -1,3 +1,6 @@ +//! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip. +//! No specific hardware is specified in this example. If you connect pin 11 and 12 you should get the same data back. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs index 2fd20159..26c258e1 100644 --- a/examples/rp/src/bin/spi_display.rs +++ b/examples/rp/src/bin/spi_display.rs @@ -1,3 +1,8 @@ +//! This example shows how to use SPI (Serial Peripheral Interface) in the RP2040 chip. +//! +//! Example written for a display using the ST7789 chip. Possibly the Waveshare Pico-ResTouch +//! (https://www.waveshare.com/wiki/Pico-ResTouch-LCD-2.8) + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/uart.rs b/examples/rp/src/bin/uart.rs index 05177a6b..451c3c39 100644 --- a/examples/rp/src/bin/uart.rs +++ b/examples/rp/src/bin/uart.rs @@ -1,3 +1,9 @@ +//! This example shows how to use UART (Universal asynchronous receiver-transmitter) in the RP2040 chip. +//! +//! No specific hardware is specified in this example. Only output on pin 0 is tested. +//! The Raspberry Pi Debug Probe (https://www.raspberrypi.com/products/debug-probe/) could be used +//! with its UART port. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs index 9df99bd5..73520171 100644 --- a/examples/rp/src/bin/uart_buffered_split.rs +++ b/examples/rp/src/bin/uart_buffered_split.rs @@ -1,3 +1,9 @@ +//! This example shows how to use UART (Universal asynchronous receiver-transmitter) in the RP2040 chip. +//! +//! No specific hardware is specified in this example. If you connect pin 0 and 1 you should get the same data back. +//! The Raspberry Pi Debug Probe (https://www.raspberrypi.com/products/debug-probe/) could be used +//! with its UART port. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs index c0943a1b..c1515a91 100644 --- a/examples/rp/src/bin/uart_unidir.rs +++ b/examples/rp/src/bin/uart_unidir.rs @@ -1,5 +1,9 @@ -//! test TX-only and RX-only UARTs. You need to connect GPIO0 to GPIO5 for +//! This example shows how to use UART (Universal asynchronous receiver-transmitter) in the RP2040 chip. +//! +//! Test TX-only and RX-only on two different UARTs. You need to connect GPIO0 to GPIO5 for //! this to work +//! The Raspberry Pi Debug Probe (https://www.raspberrypi.com/products/debug-probe/) could be used +//! with its UART port. #![no_std] #![no_main] diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 91d1ec8e..0a08f667 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -1,3 +1,7 @@ +//! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip. +//! +//! This is a CDC-NCM class implementation, aka Ethernet over USB. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/usb_logger.rs b/examples/rp/src/bin/usb_logger.rs index 7c90d0ca..9c5e6897 100644 --- a/examples/rp/src/bin/usb_logger.rs +++ b/examples/rp/src/bin/usb_logger.rs @@ -1,3 +1,7 @@ +//! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip. +//! +//! This creates the possibility to send log::info/warn/error/debug! to USB serial port. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index ca728536..164e2052 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs @@ -1,3 +1,7 @@ +//! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip. +//! +//! This creates a USB serial port that echos. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/watchdog.rs b/examples/rp/src/bin/watchdog.rs index ece5cfe3..fe5eaf92 100644 --- a/examples/rp/src/bin/watchdog.rs +++ b/examples/rp/src/bin/watchdog.rs @@ -1,3 +1,7 @@ +//! This example shows how to use Watchdog in the RP2040 chip. +//! +//! It does not work with the RP Pico W board. See wifi_blinky.rs or connect external LED and resistor. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 3e41f83b..e3e39344 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs @@ -1,3 +1,6 @@ +//! This example uses the RP Pico W board Wifi chip (cyw43). +//! Creates an Access point Wifi network and creates a TCP endpoint on port 1234. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs index 6eb207af..33d43788 100644 --- a/examples/rp/src/bin/wifi_blinky.rs +++ b/examples/rp/src/bin/wifi_blinky.rs @@ -1,3 +1,7 @@ +//! This example test the RP Pico W on board LED. +//! +//! It does not work with the RP Pico board. See blinky.rs. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index aef18aa2..743fab61 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs @@ -1,3 +1,6 @@ +//! This example uses the RP Pico W board Wifi chip (cyw43). +//! Scans Wifi for ssid names. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 4fce74a6..0223a363 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs @@ -1,3 +1,6 @@ +//! This example uses the RP Pico W board Wifi chip (cyw43). +//! Connects to specified Wifi network and creates a TCP endpoint on port 1234. + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] From 3f0c8bafb060fdf81a677f0ec37d4db11e732266 Mon Sep 17 00:00:00 2001 From: goueslati Date: Thu, 13 Jul 2023 15:20:50 +0100 Subject: [PATCH 085/148] make it work, disgustingly --- embassy-stm32-wpan/src/sub/mac/commands.rs | 42 +++++++++++++++---- embassy-stm32-wpan/src/sub/mac/consts.rs | 2 +- embassy-stm32-wpan/src/sub/mac/indications.rs | 27 ++++++------ embassy-stm32-wpan/src/sub/mac/opcodes.rs | 2 + embassy-stm32-wpan/src/sub/mac/responses.rs | 7 ++-- embassy-stm32-wpan/src/sub/mac/typedefs.rs | 26 ++++++++---- examples/stm32wb/src/bin/mac_ffd.rs | 30 +++++++++++-- examples/stm32wb/src/bin/mac_rfd.rs | 38 ++++++++++++++--- 8 files changed, 133 insertions(+), 41 deletions(-) diff --git a/embassy-stm32-wpan/src/sub/mac/commands.rs b/embassy-stm32-wpan/src/sub/mac/commands.rs index 7ccf1002..8cfa0a05 100644 --- a/embassy-stm32-wpan/src/sub/mac/commands.rs +++ b/embassy-stm32-wpan/src/sub/mac/commands.rs @@ -1,7 +1,7 @@ use super::opcodes::OpcodeM4ToM0; use super::typedefs::{ - AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, PibId, - ScanType, SecurityLevel, + AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, MacStatus, + PanId, PibId, ScanType, SecurityLevel, }; pub trait MacCommand { @@ -26,7 +26,7 @@ pub struct AssociateRequest { /// operational capabilities of the associating device pub capability_information: Capabilities, /// the identifier of the PAN with which to associate - pub coord_pan_id: [u8; 2], + pub coord_pan_id: PanId, /// the security level to be used pub security_level: SecurityLevel, /// the mode used to identify the key to be used @@ -51,7 +51,7 @@ pub struct DisassociateRequest { /// device addressing mode used pub device_addr_mode: AddressMode, /// the identifier of the PAN of the device - pub device_pan_id: [u8; 2], + pub device_pan_id: PanId, /// the reason for the disassociation pub disassociation_reason: DisassociationReason, /// device address @@ -201,7 +201,7 @@ impl MacCommand for SetRequest { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct StartRequest { /// PAN indentifier to used by the device - pub pan_id: [u8; 2], + pub pan_id: PanId, /// logical channel on which to begin pub channel_number: MacChannel, /// channel page on which to begin @@ -277,7 +277,7 @@ pub struct PollRequest { /// originator of the key to be used pub key_source: [u8; 8], /// PAN identifier of the coordinator - pub coord_pan_id: [u8; 2], + pub coord_pan_id: PanId, } impl MacCommand for PollRequest { @@ -337,7 +337,7 @@ pub struct DataRequest { /// destination addressing mode used pub dst_addr_mode: AddressMode, /// destination PAN Id - pub dst_pan_id: [u8; 2], + pub dst_pan_id: PanId, /// destination address pub dst_address: MacAddress, /// the number of octets contained in the MSDU @@ -370,6 +370,31 @@ pub struct DataRequest { pub datrate: u8, } +impl Default for DataRequest { + fn default() -> Self { + Self { + msdu_ptr: 0 as *const u8, + src_addr_mode: AddressMode::NoAddress, + dst_addr_mode: AddressMode::NoAddress, + dst_pan_id: PanId([0, 0]), + dst_address: MacAddress { short: [0, 0] }, + msdu_length: 0, + msdu_handle: 0, + ack_tx: 0, + gts_tx: false, + indirect_tx: 0, + security_level: SecurityLevel::Unsecure, + key_id_mode: KeyIdMode::Implicite, + key_index: 0, + key_source: [0u8; 8], + uwbprf: 0, + ranging: 0, + uwb_preamble_symbol_repetitions: 0, + datrate: 0, + } + } +} + impl MacCommand for DataRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsDataReq; const SIZE: usize = 40; @@ -391,6 +416,7 @@ impl MacCommand for PurgeRequest { /// MLME ASSOCIATE Response used to initiate a response to an MLME-ASSOCIATE.indication #[repr(C)] +#[derive(Default)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateResponse { /// extended address of the device requesting association @@ -399,7 +425,7 @@ pub struct AssociateResponse { /// association pub assoc_short_address: [u8; 2], /// status of the association attempt - pub status: u8, + pub status: MacStatus, /// security level to be used pub security_level: SecurityLevel, /// the originator of the key to be used diff --git a/embassy-stm32-wpan/src/sub/mac/consts.rs b/embassy-stm32-wpan/src/sub/mac/consts.rs index 892d533b..56903d98 100644 --- a/embassy-stm32-wpan/src/sub/mac/consts.rs +++ b/embassy-stm32-wpan/src/sub/mac/consts.rs @@ -1,4 +1,4 @@ -pub const MAX_ED_SCAN_RESULTS_SUPPORTED: usize = 16; pub const MAX_PAN_DESC_SUPPORTED: usize = 6; pub const MAX_SOUNDING_LIST_SUPPORTED: usize = 6; pub const MAX_PENDING_ADDRESS: usize = 7; +pub const MAX_ED_SCAN_RESULTS_SUPPORTED: usize = 16; diff --git a/embassy-stm32-wpan/src/sub/mac/indications.rs b/embassy-stm32-wpan/src/sub/mac/indications.rs index 4695f24e..b67f0a68 100644 --- a/embassy-stm32-wpan/src/sub/mac/indications.rs +++ b/embassy-stm32-wpan/src/sub/mac/indications.rs @@ -3,7 +3,7 @@ use super::event::ParseableMacEvent; use super::helpers::to_u32; use super::typedefs::{ AddressMode, Capabilities, DisassociationReason, KeyIdMode, MacAddress, MacChannel, MacStatus, PanDescriptor, - SecurityLevel, + PanId, SecurityLevel, }; /// MLME ASSOCIATE Indication which will be used by the MAC @@ -110,7 +110,7 @@ impl ParseableMacEvent for BeaconNotifyIndication { pub struct CommStatusIndication { /// The 16-bit PAN identifier of the device from which the frame /// was received or to which the frame was being sent - pub pan_id: [u8; 2], + pub pan_id: PanId, /// Source addressing mode pub src_addr_mode: AddressMode, /// Destination addressing mode @@ -163,7 +163,7 @@ impl ParseableMacEvent for CommStatusIndication { }; Ok(Self { - pan_id: [buf[0], buf[1]], + pan_id: PanId([buf[0], buf[1]]), src_addr_mode, dst_addr_mode, src_address, @@ -251,7 +251,7 @@ impl ParseableMacEvent for OrphanIndication { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SyncLossIndication { /// The PAN identifier with which the device lost synchronization or to which it was realigned - pub pan_id: [u8; 2], + pub pan_id: PanId, /// The reason that synchronization was lost pub loss_reason: u8, /// The logical channel on which the device lost synchronization or to whi @@ -275,7 +275,7 @@ impl ParseableMacEvent for SyncLossIndication { Self::validate(buf)?; Ok(Self { - pan_id: [buf[0], buf[1]], + pan_id: PanId([buf[0], buf[1]]), loss_reason: buf[2], channel_number: MacChannel::try_from(buf[3])?, channel_page: buf[4], @@ -303,19 +303,20 @@ impl ParseableMacEvent for DpsIndication { } #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(C, align(8))] pub struct DataIndication { /// Pointer to the set of octets forming the MSDU being indicated pub msdu_ptr: *const u8, /// Source addressing mode used pub src_addr_mode: AddressMode, /// Source PAN ID - pub src_pan_id: [u8; 2], + pub src_pan_id: PanId, /// Source address pub src_address: MacAddress, /// Destination addressing mode used pub dst_addr_mode: AddressMode, /// Destination PAN ID - pub dst_pan_id: [u8; 2], + pub dst_pan_id: PanId, /// Destination address pub dst_address: MacAddress, /// The number of octets contained in the MSDU being indicated @@ -355,7 +356,7 @@ pub struct DataIndication { } impl ParseableMacEvent for DataIndication { - const SIZE: usize = 72; + const SIZE: usize = 68; fn try_parse(buf: &[u8]) -> Result { Self::validate(buf)?; @@ -387,24 +388,24 @@ impl ParseableMacEvent for DataIndication { Ok(Self { msdu_ptr: to_u32(&buf[0..4]) as *const u8, src_addr_mode, - src_pan_id: [buf[5], buf[6]], + src_pan_id: PanId([buf[5], buf[6]]), src_address, dst_addr_mode, - dst_pan_id: [buf[16], buf[17]], + dst_pan_id: PanId([buf[16], buf[17]]), dst_address, msdu_length: buf[26], mpdu_link_quality: buf[27], dsn: buf[28], time_stamp: [buf[29], buf[30], buf[31], buf[32]], - security_level: SecurityLevel::try_from(buf[33])?, - key_id_mode: KeyIdMode::try_from(buf[34])?, + security_level: SecurityLevel::try_from(buf[33]).unwrap_or(SecurityLevel::Unsecure), // TODO: this is totaly wrong, but I'm too smol brain to fix it + key_id_mode: KeyIdMode::try_from(buf[34]).unwrap_or(KeyIdMode::Implicite), // TODO: this is totaly wrong, but I'm too smol brain to fix it key_source: [buf[35], buf[36], buf[37], buf[38], buf[39], buf[40], buf[41], buf[42]], key_index: buf[43], uwbprf: buf[44], uwn_preamble_symbol_repetitions: buf[45], datrate: buf[46], ranging_received: buf[47], - ranging_counter_start: to_u32(&buf[58..52]), + ranging_counter_start: to_u32(&buf[48..52]), ranging_counter_stop: to_u32(&buf[52..56]), ranging_tracking_interval: to_u32(&buf[56..60]), ranging_offset: to_u32(&buf[60..64]), diff --git a/embassy-stm32-wpan/src/sub/mac/opcodes.rs b/embassy-stm32-wpan/src/sub/mac/opcodes.rs index c9a07d6a..fd701187 100644 --- a/embassy-stm32-wpan/src/sub/mac/opcodes.rs +++ b/embassy-stm32-wpan/src/sub/mac/opcodes.rs @@ -5,6 +5,7 @@ const fn opcode(ocf: u16) -> isize { ((ST_VENDOR_OGF << 9) | (MAC_802_15_4_CMD_OPCODE_OFFSET + ocf)) as isize } +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum OpcodeM4ToM0 { MlmeAssociateReq = opcode(0x00), MlmeAssociateRes = opcode(0x01), @@ -26,6 +27,7 @@ pub enum OpcodeM4ToM0 { McpsPurgeReq = opcode(0x11), } +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum OpcodeM0ToM4 { MlmeAssociateCnf = 0x00, MlmeDisassociateCnf, diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index 37271ec2..2b90ccdc 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -2,7 +2,8 @@ use super::consts::{MAX_ED_SCAN_RESULTS_SUPPORTED, MAX_PAN_DESC_SUPPORTED, MAX_S use super::event::ParseableMacEvent; use super::helpers::to_u32; use super::typedefs::{ - AddressMode, AssociationStatus, KeyIdMode, MacAddress, MacStatus, PanDescriptor, PibId, ScanType, SecurityLevel, + AddressMode, AssociationStatus, KeyIdMode, MacAddress, MacStatus, PanDescriptor, PanId, PibId, ScanType, + SecurityLevel, }; /// MLME ASSOCIATE Confirm used to inform of the initiating device whether @@ -50,7 +51,7 @@ pub struct DisassociateConfirm { /// device addressing mode used pub device_addr_mode: AddressMode, /// the identifier of the PAN of the device - pub device_pan_id: [u8; 2], + pub device_pan_id: PanId, /// device address pub device_address: MacAddress, } @@ -76,7 +77,7 @@ impl ParseableMacEvent for DisassociateConfirm { Ok(Self { status: MacStatus::try_from(buf[0])?, device_addr_mode, - device_pan_id: [buf[2], buf[3]], + device_pan_id: PanId([buf[2], buf[3]]), device_address, }) } diff --git a/embassy-stm32-wpan/src/sub/mac/typedefs.rs b/embassy-stm32-wpan/src/sub/mac/typedefs.rs index 1a4c30cb..5ff051c9 100644 --- a/embassy-stm32-wpan/src/sub/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/sub/mac/typedefs.rs @@ -25,15 +25,12 @@ impl From for MacError { numeric_enum! { #[repr(u8)] - #[derive(Debug)] + #[derive(Debug, Default)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum MacStatus { + #[default] Success = 0x00, - Error = 0x01, - NotImplemented = 0x02, - NotSupported = 0x03, - HardwareNotSupported = 0x04, - Undefined = 0x05, + Failure = 0xFF } } @@ -134,6 +131,10 @@ impl Default for MacAddress { } } +impl MacAddress { + pub const BROADCAST: Self = Self { short: [0xFF, 0xFF] }; +} + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsCharacteristics { pub fields: u8, @@ -145,7 +146,7 @@ pub struct GtsCharacteristics { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PanDescriptor { /// PAN identifier of the coordinator - pub coord_pan_id: [u8; 2], + pub coord_pan_id: PanId, /// Coordinator addressing mode pub coord_addr_mode: AddressMode, /// The current logical channel occupied by the network @@ -188,7 +189,7 @@ impl TryFrom<&[u8]> for PanDescriptor { }; Ok(Self { - coord_pan_id: [buf[0], buf[1]], + coord_pan_id: PanId([buf[0], buf[1]]), coord_addr_mode, logical_channel: MacChannel::try_from(buf[3])?, coord_addr, @@ -336,3 +337,12 @@ numeric_enum! { Orphan = 0x03 } } + +/// newtype for Pan Id +#[derive(Default, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct PanId(pub [u8; 2]); + +impl PanId { + pub const BROADCAST: Self = Self([0xFF, 0xFF]); +} diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 4e2578a2..37d36fcd 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -6,8 +6,9 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::sub::mac::commands::{ResetRequest, SetRequest, StartRequest}; -use embassy_stm32_wpan::sub::mac::typedefs::{MacChannel, PibId}; +use embassy_stm32_wpan::sub::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest}; +use embassy_stm32_wpan::sub::mac::event::MacEvent; +use embassy_stm32_wpan::sub::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel}; use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -123,7 +124,7 @@ async fn main(spawner: Spawner) { info!("starting FFD device"); mbox.mac_subsystem .send_command(&StartRequest { - pan_id: [0xAA, 0x1A], + pan_id: PanId([0x1A, 0xAA]), channel_number: MacChannel::Channel16, beacon_order: 0x0F, superframe_order: 0x0F, @@ -151,5 +152,28 @@ async fn main(spawner: Spawner) { loop { let evt = mbox.mac_subsystem.read().await; defmt::info!("{:#x}", evt); + + if let Ok(evt) = evt { + match evt { + MacEvent::MlmeAssociateInd(association) => mbox + .mac_subsystem + .send_command(&AssociateResponse { + device_address: association.device_address, + assoc_short_address: [0x33, 0x44], + status: MacStatus::Success, + security_level: SecurityLevel::Unsecure, + ..Default::default() + }) + .await + .unwrap(), + MacEvent::McpsDataInd(data_ind) => { + let data_addr = data_ind.msdu_ptr; + let mut a = [0u8; 256]; + unsafe { data_addr.copy_to(&mut a as *mut _, data_ind.msdu_length as usize) } + info!("{}", a[..data_ind.msdu_length as usize]) + } + _ => {} + } + } } } diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index e5f8d54c..75670913 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -6,10 +6,10 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, GetRequest, ResetRequest, SetRequest}; +use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, DataRequest, GetRequest, ResetRequest, SetRequest}; use embassy_stm32_wpan::sub::mac::event::MacEvent; use embassy_stm32_wpan::sub::mac::typedefs::{ - AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PibId, SecurityLevel, + AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PanId, PibId, SecurityLevel, }; use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; @@ -112,7 +112,7 @@ async fn main(spawner: Spawner) { coord_addr_mode: AddressMode::Short, coord_address: MacAddress { short: [34, 17] }, capability_information: Capabilities::ALLOCATE_ADDRESS, - coord_pan_id: [0xAA, 0x1A], + coord_pan_id: PanId([0x1A, 0xAA]), security_level: SecurityLevel::Unsecure, key_id_mode: KeyIdMode::Implicite, key_source: [0; 8], @@ -123,11 +123,16 @@ async fn main(spawner: Spawner) { let evt = mbox.mac_subsystem.read().await; info!("{:#x}", evt); + let short_addr = if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt { + conf.assoc_short_address + } else { + defmt::panic!() + }; + info!("setting short address"); - let short: u64 = 0xACDE480000000002; mbox.mac_subsystem .send_command(&SetRequest { - pib_attribute_ptr: &short as *const _ as *const u8, + pib_attribute_ptr: &short_addr as *const _ as *const u8, pib_attribute: PibId::ShortAddress, }) .await @@ -135,6 +140,29 @@ async fn main(spawner: Spawner) { let evt = mbox.mac_subsystem.read().await; info!("{:#x}", evt); + info!("sending data"); + let mut data_buffer = [0u8; 256]; + let data = b"Hello from embassy!"; + data_buffer[..data.len()].copy_from_slice(data); + mbox.mac_subsystem + .send_command(&DataRequest { + src_addr_mode: AddressMode::Short, + dst_addr_mode: AddressMode::Short, + dst_pan_id: PanId::BROADCAST, + dst_address: MacAddress::BROADCAST, + msdu_handle: 0x02, + ack_tx: 0x00, + gts_tx: false, + msdu_ptr: &data_buffer as *const _ as *const u8, + msdu_length: data.len() as u8, + security_level: SecurityLevel::Unsecure, + ..Default::default() + }) + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + loop { let evt = mbox.mac_subsystem.read().await; info!("{:#x}", evt); From 68792bb9188b69c1e7629425a0d39110c602b9b2 Mon Sep 17 00:00:00 2001 From: goueslati Date: Thu, 13 Jul 2023 15:48:15 +0100 Subject: [PATCH 086/148] final structs unchecked --- embassy-stm32-wpan/src/sub/mac/indications.rs | 23 ++++++++++++-- embassy-stm32-wpan/src/sub/mac/responses.rs | 31 +++++++++++++++++-- embassy-stm32-wpan/src/sub/mac/typedefs.rs | 17 +++++++++- 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/embassy-stm32-wpan/src/sub/mac/indications.rs b/embassy-stm32-wpan/src/sub/mac/indications.rs index b67f0a68..6df4aa23 100644 --- a/embassy-stm32-wpan/src/sub/mac/indications.rs +++ b/embassy-stm32-wpan/src/sub/mac/indications.rs @@ -96,12 +96,31 @@ pub struct BeaconNotifyIndication { } impl ParseableMacEvent for BeaconNotifyIndication { - const SIZE: usize = 12; + const SIZE: usize = 88; fn try_parse(buf: &[u8]) -> Result { + // TODO: this is unchecked + Self::validate(buf)?; - todo!() + let addr_list = [ + MacAddress::try_from(&buf[26..34])?, + MacAddress::try_from(&buf[34..42])?, + MacAddress::try_from(&buf[42..50])?, + MacAddress::try_from(&buf[50..58])?, + MacAddress::try_from(&buf[58..66])?, + MacAddress::try_from(&buf[66..74])?, + MacAddress::try_from(&buf[74..82])?, + ]; + + Ok(Self { + sdu_ptr: to_u32(&buf[0..4]) as *const u8, + pan_descriptor: PanDescriptor::try_from(&buf[4..26])?, + addr_list, + bsn: buf[82], + pend_addr_spec: buf[83], + sdu_length: buf[83], + }) } } diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index 2b90ccdc..0d3c0986 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -199,12 +199,39 @@ pub struct ScanConfirm { } impl ParseableMacEvent for ScanConfirm { - const SIZE: usize = 9; + const SIZE: usize = 185; fn try_parse(buf: &[u8]) -> Result { + // TODO: this is unchecked + Self::validate(buf)?; - todo!() + let mut energy_detect_list = [0; MAX_ED_SCAN_RESULTS_SUPPORTED]; + energy_detect_list.copy_from_slice(&buf[8..24]); + + let pan_descriptor_list = [ + PanDescriptor::try_from(&buf[24..46])?, + PanDescriptor::try_from(&buf[46..68])?, + PanDescriptor::try_from(&buf[68..90])?, + PanDescriptor::try_from(&buf[90..102])?, + PanDescriptor::try_from(&buf[102..124])?, + PanDescriptor::try_from(&buf[124..146])?, + ]; + + let mut uwb_energy_detect_list = [0; MAX_ED_SCAN_RESULTS_SUPPORTED]; + uwb_energy_detect_list.copy_from_slice(&buf[147..163]); + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + scan_type: ScanType::try_from(buf[1])?, + channel_page: buf[2], + unscanned_channels: [buf[3], buf[4], buf[5], buf[6]], + result_list_size: buf[7], + energy_detect_list, + pan_descriptor_list, + detected_category: buf[146], + uwb_energy_detect_list, + }) } } diff --git a/embassy-stm32-wpan/src/sub/mac/typedefs.rs b/embassy-stm32-wpan/src/sub/mac/typedefs.rs index 5ff051c9..30c7731b 100644 --- a/embassy-stm32-wpan/src/sub/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/sub/mac/typedefs.rs @@ -135,6 +135,21 @@ impl MacAddress { pub const BROADCAST: Self = Self { short: [0xFF, 0xFF] }; } +impl TryFrom<&[u8]> for MacAddress { + type Error = (); + + fn try_from(buf: &[u8]) -> Result { + const SIZE: usize = 8; + if buf.len() < SIZE { + return Err(()); + } + + Ok(Self { + extended: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], + }) + } +} + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsCharacteristics { pub fields: u8, @@ -171,7 +186,7 @@ impl TryFrom<&[u8]> for PanDescriptor { type Error = (); fn try_from(buf: &[u8]) -> Result { - const SIZE: usize = 24; + const SIZE: usize = 22; if buf.len() < SIZE { return Err(()); } From f90b170dad91848d5a0ff746d873bd8a4ce7e91f Mon Sep 17 00:00:00 2001 From: goueslati Date: Thu, 13 Jul 2023 16:29:29 +0100 Subject: [PATCH 087/148] cleanup --- embassy-stm32-wpan/Cargo.toml | 2 +- embassy-stm32-wpan/src/sub/mac/mod.rs | 2 -- embassy-stm32-wpan/src/sub/mac/responses.rs | 2 -- embassy-stm32-wpan/src/sub/sys.rs | 8 ++++---- examples/stm32wb/.cargo/config.toml | 4 ++-- examples/stm32wb/src/bin/mac_ffd.rs | 10 +++++++--- examples/stm32wb/src/bin/mac_rfd.rs | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 1325faed..91540321 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -29,7 +29,7 @@ stm32wb-hci = { version = "0.1.2", features = ["version-5-0"], optional = true } bitflags = { version = "2.3.3", optional = true } [features] -default = ["stm32wb55rg", "mac", "ble", "defmt"] +default = [] defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] ble = ["dep:stm32wb-hci"] diff --git a/embassy-stm32-wpan/src/sub/mac/mod.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs index 26358bf8..ab39f89c 100644 --- a/embassy-stm32-wpan/src/sub/mac/mod.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -98,8 +98,6 @@ impl Mac { let mut payload = [0u8; MAX_PACKET_SIZE]; cmd.copy_into_slice(&mut payload); - debug!("sending {}", &payload[..T::SIZE]); - let response = self .tl_write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]) .await; diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index 0d3c0986..2f6f5bf5 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -28,8 +28,6 @@ impl ParseableMacEvent for AssociateConfirm { const SIZE: usize = 16; fn try_parse(buf: &[u8]) -> Result { - debug!("{}", buf); - Self::validate(buf)?; Ok(Self { diff --git a/embassy-stm32-wpan/src/sub/sys.rs b/embassy-stm32-wpan/src/sub/sys.rs index caa4845f..c17fd531 100644 --- a/embassy-stm32-wpan/src/sub/sys.rs +++ b/embassy-stm32-wpan/src/sub/sys.rs @@ -50,7 +50,7 @@ impl Sys { } /// `HW_IPCC_SYS_CmdEvtNot` - pub async fn write_and_get_response(&self, opcode: ShciOpcode, payload: &[u8]) -> SchiCommandStatus { + pub async fn write_and_get_response(&self, opcode: ShciOpcode, payload: &[u8]) -> Result { self.write(opcode, payload).await; Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await; @@ -59,12 +59,12 @@ impl Sys { let p_command_event = &((*p_event_packet).evt_serial.evt.payload) as *const _ as *const CcEvt; let p_payload = &((*p_command_event).payload) as *const u8; - ptr::read_volatile(p_payload).try_into().unwrap() + ptr::read_volatile(p_payload).try_into() } } #[cfg(feature = "mac")] - pub async fn shci_c2_mac_802_15_4_init(&self) -> SchiCommandStatus { + pub async fn shci_c2_mac_802_15_4_init(&self) -> Result { use crate::tables::{ Mac802_15_4Table, TracesTable, MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, TL_MAC_802_15_4_TABLE, TL_TRACES_TABLE, TRACES_EVT_QUEUE, @@ -88,7 +88,7 @@ impl Sys { } #[cfg(feature = "ble")] - pub async fn shci_c2_ble_init(&self, param: ShciBleInitCmdParam) -> SchiCommandStatus { + pub async fn shci_c2_ble_init(&self, param: ShciBleInitCmdParam) -> Result { self.write_and_get_response(ShciOpcode::BleInit, param.payload()).await } diff --git a/examples/stm32wb/.cargo/config.toml b/examples/stm32wb/.cargo/config.toml index cf62a10a..51c499ee 100644 --- a/examples/stm32wb/.cargo/config.toml +++ b/examples/stm32wb/.cargo/config.toml @@ -1,7 +1,7 @@ [target.'cfg(all(target_arch = "arm", target_os = "none"))'] # replace STM32WB55CCUx with your chip as listed in `probe-rs chip list` -runner = "probe-run --chip STM32WB55RGVx --speed 1000 --connect-under-reset" -# runner = "teleprobe local run --chip STM32WB55RG --elf" +# runner = "probe-run --chip STM32WB55RGVx --speed 1000 --connect-under-reset" +runner = "teleprobe local run --chip STM32WB55RG --elf" [build] target = "thumbv7em-none-eabihf" diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 37d36fcd..689a2835 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -168,9 +168,13 @@ async fn main(spawner: Spawner) { .unwrap(), MacEvent::McpsDataInd(data_ind) => { let data_addr = data_ind.msdu_ptr; - let mut a = [0u8; 256]; - unsafe { data_addr.copy_to(&mut a as *mut _, data_ind.msdu_length as usize) } - info!("{}", a[..data_ind.msdu_length as usize]) + let mut data = [0u8; 256]; + unsafe { data_addr.copy_to(&mut data as *mut _, data_ind.msdu_length as usize) } + info!("{}", data[..data_ind.msdu_length as usize]); + + if &data[..data_ind.msdu_length as usize] == b"Hello from embassy!" { + info!("success"); + } } _ => {} } diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index 75670913..ea349f9a 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -148,7 +148,7 @@ async fn main(spawner: Spawner) { .send_command(&DataRequest { src_addr_mode: AddressMode::Short, dst_addr_mode: AddressMode::Short, - dst_pan_id: PanId::BROADCAST, + dst_pan_id: PanId([0x1A, 0xAA]), dst_address: MacAddress::BROADCAST, msdu_handle: 0x02, ack_tx: 0x00, From 460cdc9e0f51979e27dbd0a8faaad2738760cdf3 Mon Sep 17 00:00:00 2001 From: Ben Simms Date: Thu, 13 Jul 2023 19:29:09 +0100 Subject: [PATCH 088/148] Check intrstatus before signalling suspended --- embassy-rp/src/usb.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs index b3f3bd92..4ab881f6 100644 --- a/embassy-rp/src/usb.rs +++ b/embassy-rp/src/usb.rs @@ -361,6 +361,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { let regs = T::regs(); let siestatus = regs.sie_status().read(); + let intrstatus = regs.intr().read(); if siestatus.resume() { regs.sie_status().write(|w| w.set_resume(true)); @@ -389,7 +390,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { return Poll::Ready(Event::Reset); } - if siestatus.suspended() { + if siestatus.suspended() && intrstatus.dev_suspend() { regs.sie_status().write(|w| w.set_suspended(true)); return Poll::Ready(Event::Suspend); } From 56ca1794759a21d9d5397e5bd4aa8226f6ef9385 Mon Sep 17 00:00:00 2001 From: Henrik Berg Date: Thu, 13 Jul 2023 22:47:03 +0200 Subject: [PATCH 089/148] Round temp to make more sense. --- examples/rp/src/bin/adc.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs index c0cbe017..81a8b834 100644 --- a/examples/rp/src/bin/adc.rs +++ b/examples/rp/src/bin/adc.rs @@ -41,5 +41,8 @@ async fn main(_spawner: Spawner) { fn convert_to_celsius(raw_temp: u16) -> f32 { // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet - 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721 + let temp = 27.0 - (raw_temp as f32 * 3.3 / 4096.0 - 0.706) / 0.001721; + let sign = if temp < 0.0 { -1.0 } else { 1.0 }; + let rounded_temp_x10: i16 = ((temp * 10.0) + 0.5 * sign) as i16; + (rounded_temp_x10 as f32) / 10.0 } From 3bae53306683a57020ba751afaf631ec169deeed Mon Sep 17 00:00:00 2001 From: Phil Markgraf Date: Sat, 15 Jul 2023 04:40:23 -0700 Subject: [PATCH 090/148] Enable RTC on STM32WL chips (#1645) * Add clippy allow to not report if same then branch * Support enabling RTC clock on STM32WL * Add clippy allow to not report if same then branch * Support enabling RTC clock on STM32WL * Add rtc example for stm32wl * Address code review feedback --- embassy-stm32/src/rcc/wl.rs | 61 ++++++++++++++++++++++++++++- embassy-stm32/src/rtc/v3.rs | 1 + examples/stm32wl/.cargo/config.toml | 2 +- examples/stm32wl/Cargo.toml | 5 ++- examples/stm32wl/src/bin/rtc.rs | 43 ++++++++++++++++++++ 5 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 examples/stm32wl/src/bin/rtc.rs diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index 7072db98..6b69bb1c 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs @@ -1,4 +1,5 @@ -use crate::pac::{FLASH, RCC}; +use crate::pac::pwr::vals::Dbp; +use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -184,6 +185,8 @@ pub struct Config { pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, pub enable_lsi: bool, + pub enable_rtc_apb: bool, + pub rtc_mux: RtcClockSource, } impl Default for Config { @@ -196,10 +199,25 @@ impl Default for Config { apb1_pre: APBPrescaler::NotDivided, apb2_pre: APBPrescaler::NotDivided, enable_lsi: false, + enable_rtc_apb: false, + rtc_mux: RtcClockSource::LSI32, } } } +pub enum RtcClockSource { + LSE32, + LSI32, +} + +#[repr(u8)] +pub enum Lsedrv { + Low = 0, + MediumLow = 1, + MediumHigh = 2, + High = 3, +} + pub(crate) unsafe fn init(config: Config) { let (sys_clk, sw, vos) = match config.mux { ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::Range2), @@ -266,6 +284,32 @@ pub(crate) unsafe fn init(config: Config) { while FLASH.acr().read().latency() != ws {} + match config.rtc_mux { + RtcClockSource::LSE32 => { + // 1. Unlock the backup domain + PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED)); + + // 2. Setup the LSE + RCC.bdcr().modify(|w| { + // Enable LSE + w.set_lseon(true); + // Max drive strength + // TODO: should probably be settable + w.set_lsedrv(Lsedrv::High as u8); //---// PAM - should not be commented + }); + + // Wait until LSE is running + while !RCC.bdcr().read().lserdy() {} + } + RtcClockSource::LSI32 => { + // 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() {} + } + } + match config.mux { ClockSrc::HSI16 => { // Enable HSI16 @@ -287,11 +331,26 @@ pub(crate) unsafe fn init(config: Config) { w.set_msirgsel(true); w.set_msirange(range.into()); w.set_msion(true); + + if let RtcClockSource::LSE32 = config.rtc_mux { + // If LSE is enabled, enable calibration of MSI + w.set_msipllen(true); + } else { + w.set_msipllen(false); + } }); while !RCC.cr().read().msirdy() {} } } + if config.enable_rtc_apb { + // enable peripheral clock for communication + crate::pac::RCC.apb1enr1().modify(|w| w.set_rtcapben(true)); + + // read to allow the pwr clock to enable + crate::pac::PWR.cr1().read(); + } + RCC.extcfgr().modify(|w| { if config.shd_ahb_pre == AHBPrescaler::NotDivided { w.set_shdhpre(0); diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 7e5c64d9..8ef0ec51 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -172,6 +172,7 @@ impl sealed::Instance for crate::peripherals::RTC { const BACKUP_REGISTER_COUNT: usize = 32; fn read_backup_register(_rtc: &Rtc, register: usize) -> Option { + #[allow(clippy::if_same_then_else)] if register < Self::BACKUP_REGISTER_COUNT { //Some(rtc.bkpr()[register].read().bits()) None // RTC3 backup registers come from the TAMP peripe=heral, not RTC. Not() even in the L412 PAC diff --git a/examples/stm32wl/.cargo/config.toml b/examples/stm32wl/.cargo/config.toml index 4f8094ff..ee416fcb 100644 --- a/examples/stm32wl/.cargo/config.toml +++ b/examples/stm32wl/.cargo/config.toml @@ -3,7 +3,7 @@ runner = "probe-rs run --chip STM32WLE5JCIx" [build] -target = "thumbv7em-none-eabihf" +target = "thumbv7em-none-eabi" [env] DEFMT_LOG = "trace" diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 99f68387..e2c66f45 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -8,8 +8,8 @@ license = "MIT OR Apache-2.0" embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti"] } -embassy-embedded-hal = {version = "0.1.0", path = "../../embassy-embedded-hal" } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti", "chrono"] } +embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] } lora-phy = { version = "1" } lorawan-device = { version = "0.10.0", default-features = false, features = ["async", "external-lora-phy"] } @@ -25,6 +25,7 @@ embedded-storage = "0.3.0" 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 } [patch.crates-io] lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs new file mode 100644 index 00000000..e1182549 --- /dev/null +++ b/examples/stm32wl/src/bin/rtc.rs @@ -0,0 +1,43 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +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::Config; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +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.enable_rtc_apb = true; + 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().clock_config(embassy_stm32::rtc::RtcClockSource::LSE), + ); + info!("Got RTC! {:?}", now.timestamp()); + + rtc.set_datetime(now.into()).expect("datetime not set"); + + // In reality the delay would be much longer + Timer::after(Duration::from_millis(20000)).await; + + let then: NaiveDateTime = rtc.now().unwrap().into(); + info!("Got RTC! {:?}", then.timestamp()); +} From 5b076cb0ddb55e60ae24d1a0ae02b27baa5d84e5 Mon Sep 17 00:00:00 2001 From: GhaithOueslati Date: Sat, 15 Jul 2023 13:33:10 +0100 Subject: [PATCH 091/148] wpan: update `stm32wb-hci` to version 0.1.3 --- embassy-stm32-wpan/Cargo.toml | 4 ++-- examples/stm32wb/Cargo.toml | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 5141f9bd..6142fd7d 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -25,10 +25,10 @@ aligned = "0.4.1" bit_field = "0.10.2" stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } -stm32wb-hci = { version = "0.1.2", features = ["version-5-0"], optional = true } +stm32wb-hci = { version = "0.1.3", optional = true } [features] -defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] +defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci/defmt"] ble = ["dep:stm32wb-hci"] mac = [] diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 203ca148..26e72991 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -37,7 +37,4 @@ required-features = ["mac"] [[bin]] name = "eddystone_beacon" -required-features = ["ble"] - -[patch.crates-io] -stm32wb-hci = { git = "https://github.com/OueslatiGhaith/stm32wb-hci", rev = "9f663be"} \ No newline at end of file +required-features = ["ble"] \ No newline at end of file From 283ec756a958cffa0ba145af6c9aea8c862430fa Mon Sep 17 00:00:00 2001 From: GhaithOueslati Date: Sat, 15 Jul 2023 13:37:41 +0100 Subject: [PATCH 092/148] stm32wb: add gatt server example --- examples/stm32wb/Cargo.toml | 4 + examples/stm32wb/src/bin/gatt_server.rs | 397 ++++++++++++++++++++++++ 2 files changed, 401 insertions(+) create mode 100644 examples/stm32wb/src/bin/gatt_server.rs diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 26e72991..d8d5f0ec 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -37,4 +37,8 @@ required-features = ["mac"] [[bin]] name = "eddystone_beacon" +required-features = ["ble"] + +[[bin]] +name = "gatt_server" required-features = ["ble"] \ No newline at end of file diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs new file mode 100644 index 00000000..7621efb1 --- /dev/null +++ b/examples/stm32wb/src/bin/gatt_server.rs @@ -0,0 +1,397 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use core::time::Duration; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::bind_interrupts; +use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32_wpan::hci::event::command::{CommandComplete, ReturnParameters}; +use embassy_stm32_wpan::hci::host::uart::{Packet, UartHci}; +use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; +use embassy_stm32_wpan::hci::types::AdvertisingType; +use embassy_stm32_wpan::hci::vendor::stm32wb::command::gap::{ + AddressType, AuthenticationRequirements, DiscoverableParameters, GapCommands, IoCapability, LocalName, Pin, Role, + SecureConnectionSupport, +}; +use embassy_stm32_wpan::hci::vendor::stm32wb::command::gatt::{ + AddCharacteristicParameters, AddServiceParameters, CharacteristicEvent, CharacteristicPermission, + CharacteristicProperty, EncryptionKeySize, GattCommands, ServiceType, UpdateCharacteristicValueParameters, Uuid, + WriteResponseParameters, +}; +use embassy_stm32_wpan::hci::vendor::stm32wb::command::hal::{ConfigData, HalCommands, PowerLevel}; +use embassy_stm32_wpan::hci::vendor::stm32wb::event::{self, AttributeHandle, Stm32Wb5xEvent}; +use embassy_stm32_wpan::hci::{BdAddr, Event}; +use embassy_stm32_wpan::lhci::LhciC1DeviceInformationCcrp; +use embassy_stm32_wpan::sub::ble::Ble; +use embassy_stm32_wpan::TlMbox; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs{ + IPCC_C1_RX => ReceiveInterruptHandler; + IPCC_C1_TX => TransmitInterruptHandler; +}); + +const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + /* + How to make this work: + + - Obtain a NUCLEO-STM32WB55 from your preferred supplier. + - Download and Install STM32CubeProgrammer. + - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from + gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x + - Open STM32CubeProgrammer + - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. + - Once complete, click connect to connect to the device. + - On the left hand pane, click the RSS signal icon to open "Firmware Upgrade Services". + - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file + - Select that file, the memory address, "verify download", and then "Firmware Upgrade". + - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the + stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. + - Select that file, the memory address, "verify download", and then "Firmware Upgrade". + - Select "Start Wireless Stack". + - Disconnect from the device. + - In the examples folder for stm32wb, modify the memory.x file to match your target device. + - Run this example. + + Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. + */ + + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + + let config = Config::default(); + let mut mbox = TlMbox::init(p.IPCC, Irqs, config); + + let sys_event = mbox.sys_subsystem.read().await; + info!("sys event: {}", sys_event.payload()); + + mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; + + info!("resetting BLE..."); + mbox.ble_subsystem.reset().await; + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + info!("config public address..."); + mbox.ble_subsystem + .write_config_data(&ConfigData::public_address(get_bd_addr()).build()) + .await; + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + info!("config random address..."); + mbox.ble_subsystem + .write_config_data(&ConfigData::random_address(get_random_addr()).build()) + .await; + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + info!("config identity root..."); + mbox.ble_subsystem + .write_config_data(&ConfigData::identity_root(&get_irk()).build()) + .await; + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + info!("config encryption root..."); + mbox.ble_subsystem + .write_config_data(&ConfigData::encryption_root(&get_erk()).build()) + .await; + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + info!("config tx power level..."); + mbox.ble_subsystem.set_tx_power_level(PowerLevel::ZerodBm).await; + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + info!("GATT init..."); + mbox.ble_subsystem.init_gatt().await; + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + info!("GAP init..."); + mbox.ble_subsystem + .init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH) + .await; + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + info!("set IO capabilities..."); + mbox.ble_subsystem.set_io_capability(IoCapability::DisplayConfirm).await; + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + info!("set authentication requirements..."); + mbox.ble_subsystem + .set_authentication_requirement(&AuthenticationRequirements { + bonding_required: false, + keypress_notification_support: false, + mitm_protection_required: false, + encryption_key_size_range: (8, 16), + fixed_pin: Pin::Requested, + identity_address_type: AddressType::Public, + secure_connection_support: SecureConnectionSupport::Optional, + }) + .await + .unwrap(); + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + info!("set scan response data..."); + mbox.ble_subsystem.le_set_scan_response_data(b"TXTX").await.unwrap(); + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + info!("set scan response data..."); + mbox.ble_subsystem.le_set_scan_response_data(b"TXTX").await.unwrap(); + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + defmt::info!("initializing services and characteristics..."); + let mut ble_context = init_gatt_services(&mut mbox.ble_subsystem).await.unwrap(); + defmt::info!("{}", ble_context); + + let discovery_params = DiscoverableParameters { + advertising_type: AdvertisingType::ConnectableUndirected, + advertising_interval: Some((Duration::from_millis(100), Duration::from_millis(100))), + address_type: OwnAddressType::Public, + filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan, + local_name: Some(LocalName::Complete(b"TXTX")), + advertising_data: &[], + conn_interval: (None, None), + }; + + info!("set discoverable..."); + mbox.ble_subsystem.set_discoverable(&discovery_params).await.unwrap(); + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + loop { + let response = mbox.ble_subsystem.read().await; + defmt::debug!("{}", response); + + if let Ok(Packet::Event(event)) = response { + match event { + Event::LeConnectionComplete(_) => { + defmt::info!("connected"); + } + Event::DisconnectionComplete(_) => { + defmt::info!("disconnected"); + ble_context.is_subscribed = false; + mbox.ble_subsystem.set_discoverable(&discovery_params).await.unwrap(); + } + Event::Vendor(vendor_event) => match vendor_event { + Stm32Wb5xEvent::AttReadPermitRequest(read_req) => { + defmt::info!("read request received {}, allowing", read_req); + mbox.ble_subsystem.allow_read(read_req.conn_handle).await + } + Stm32Wb5xEvent::AttWritePermitRequest(write_req) => { + defmt::info!("write request received {}, allowing", write_req); + mbox.ble_subsystem + .write_response(&WriteResponseParameters { + conn_handle: write_req.conn_handle, + attribute_handle: write_req.attribute_handle, + status: Ok(()), + value: write_req.value(), + }) + .await + .unwrap() + } + Stm32Wb5xEvent::GattAttributeModified(attribute) => { + defmt::info!("{}", ble_context); + if attribute.attr_handle.0 == ble_context.chars.notify.0 + 2 { + if attribute.data()[0] == 0x01 { + defmt::info!("subscribed"); + ble_context.is_subscribed = true; + } else { + defmt::info!("unsubscribed"); + ble_context.is_subscribed = false; + } + } + } + _ => {} + }, + _ => {} + } + } + } +} + +fn get_bd_addr() -> BdAddr { + let mut bytes = [0u8; 6]; + + let lhci_info = LhciC1DeviceInformationCcrp::new(); + bytes[0] = (lhci_info.uid64 & 0xff) as u8; + bytes[1] = ((lhci_info.uid64 >> 8) & 0xff) as u8; + bytes[2] = ((lhci_info.uid64 >> 16) & 0xff) as u8; + bytes[3] = lhci_info.device_type_id; + bytes[4] = (lhci_info.st_company_id & 0xff) as u8; + bytes[5] = (lhci_info.st_company_id >> 8 & 0xff) as u8; + + BdAddr(bytes) +} + +fn get_random_addr() -> BdAddr { + let mut bytes = [0u8; 6]; + + let lhci_info = LhciC1DeviceInformationCcrp::new(); + bytes[0] = (lhci_info.uid64 & 0xff) as u8; + bytes[1] = ((lhci_info.uid64 >> 8) & 0xff) as u8; + bytes[2] = ((lhci_info.uid64 >> 16) & 0xff) as u8; + bytes[3] = 0; + bytes[4] = 0x6E; + bytes[5] = 0xED; + + BdAddr(bytes) +} + +const BLE_CFG_IRK: [u8; 16] = [ + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, +]; +const BLE_CFG_ERK: [u8; 16] = [ + 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21, 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x21, +]; + +fn get_irk() -> EncryptionKey { + EncryptionKey(BLE_CFG_IRK) +} + +fn get_erk() -> EncryptionKey { + EncryptionKey(BLE_CFG_ERK) +} + +#[derive(defmt::Format)] +pub struct BleContext { + pub service_handle: AttributeHandle, + pub chars: CharHandles, + pub is_subscribed: bool, +} + +#[derive(defmt::Format)] +pub struct CharHandles { + pub read: AttributeHandle, + pub write: AttributeHandle, + pub notify: AttributeHandle, +} + +pub async fn init_gatt_services(ble_subsystem: &mut Ble) -> Result { + let service_handle = gatt_add_service(ble_subsystem, Uuid::Uuid16(0x500)).await?; + + let read = gatt_add_char( + ble_subsystem, + service_handle, + Uuid::Uuid16(0x501), + CharacteristicProperty::READ, + Some(b"Hello from embassy!"), + ) + .await?; + + let write = gatt_add_char( + ble_subsystem, + service_handle, + Uuid::Uuid16(0x502), + CharacteristicProperty::WRITE_WITHOUT_RESPONSE | CharacteristicProperty::WRITE | CharacteristicProperty::READ, + None, + ) + .await?; + + let notify = gatt_add_char( + ble_subsystem, + service_handle, + Uuid::Uuid16(0x503), + CharacteristicProperty::NOTIFY | CharacteristicProperty::READ, + None, + ) + .await?; + + Ok(BleContext { + service_handle, + is_subscribed: false, + chars: CharHandles { read, write, notify }, + }) +} + +async fn gatt_add_service(ble_subsystem: &mut Ble, uuid: Uuid) -> Result { + ble_subsystem + .add_service(&AddServiceParameters { + uuid, + service_type: ServiceType::Primary, + max_attribute_records: 8, + }) + .await; + let response = ble_subsystem.read().await; + defmt::debug!("{}", response); + + if let Ok(Packet::Event(Event::CommandComplete(CommandComplete { + return_params: + ReturnParameters::Vendor(event::command::ReturnParameters::GattAddService(event::command::GattService { + service_handle, + .. + })), + .. + }))) = response + { + Ok(service_handle) + } else { + Err(()) + } +} + +async fn gatt_add_char( + ble_subsystem: &mut Ble, + service_handle: AttributeHandle, + characteristic_uuid: Uuid, + characteristic_properties: CharacteristicProperty, + default_value: Option<&[u8]>, +) -> Result { + ble_subsystem + .add_characteristic(&AddCharacteristicParameters { + service_handle, + characteristic_uuid, + characteristic_properties, + characteristic_value_len: 32, + security_permissions: CharacteristicPermission::empty(), + gatt_event_mask: CharacteristicEvent::all(), + encryption_key_size: EncryptionKeySize::with_value(7).unwrap(), + is_variable: true, + }) + .await; + let response = ble_subsystem.read().await; + defmt::debug!("{}", response); + + if let Ok(Packet::Event(Event::CommandComplete(CommandComplete { + return_params: + ReturnParameters::Vendor(event::command::ReturnParameters::GattAddCharacteristic( + event::command::GattCharacteristic { + characteristic_handle, .. + }, + )), + .. + }))) = response + { + if let Some(value) = default_value { + ble_subsystem + .update_characteristic_value(&UpdateCharacteristicValueParameters { + service_handle, + characteristic_handle, + offset: 0, + value, + }) + .await + .unwrap(); + + let response = ble_subsystem.read().await; + defmt::debug!("{}", response); + } + Ok(characteristic_handle) + } else { + Err(()) + } +} From 0628dd997f872d49ba10e299d250f4877434d6f1 Mon Sep 17 00:00:00 2001 From: GhaithOueslati Date: Sat, 15 Jul 2023 13:52:04 +0100 Subject: [PATCH 093/148] fix test --- tests/stm32/Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 4fd4a6d0..d94bd730 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -46,9 +46,6 @@ rand_chacha = { version = "0.3", default-features = false } chrono = { version = "^0.4", default-features = false, optional = true} -[patch.crates-io] -stm32wb-hci = { git = "https://github.com/OueslatiGhaith/stm32wb-hci", rev = "9f663be"} - # BEGIN TESTS # Generated by gen_test.py. DO NOT EDIT. [[bin]] From 7ec7d1bbccac07de6053e1a152b6c417693e919b Mon Sep 17 00:00:00 2001 From: Ghaith Oueslati <73850124+OueslatiGhaith@users.noreply.github.com> Date: Sat, 15 Jul 2023 14:56:26 +0100 Subject: [PATCH 094/148] fix ci issue --- embassy-stm32-wpan/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 6142fd7d..f1242ea1 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -28,7 +28,7 @@ stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } stm32wb-hci = { version = "0.1.3", optional = true } [features] -defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci/defmt"] +defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"] ble = ["dep:stm32wb-hci"] mac = [] @@ -48,4 +48,4 @@ stm32wb55rg = [ "embassy-stm32/stm32wb55rg" ] stm32wb55vc = [ "embassy-stm32/stm32wb55vc" ] stm32wb55ve = [ "embassy-stm32/stm32wb55ve" ] stm32wb55vg = [ "embassy-stm32/stm32wb55vg" ] -stm32wb55vy = [ "embassy-stm32/stm32wb55vy" ] \ No newline at end of file +stm32wb55vy = [ "embassy-stm32/stm32wb55vy" ] From 48b37aa2bf83b8fccb293fcda7f51149a4ec1a24 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 09:32:36 -0500 Subject: [PATCH 095/148] stm32/eth: refactor genericsmi --- embassy-stm32/src/eth/generic_smi.rs | 10 +++++++--- embassy-stm32/src/eth/mod.rs | 10 ++++------ embassy-stm32/src/eth/v1/mod.rs | 27 ++++++++++++++++++--------- embassy-stm32/src/eth/v2/mod.rs | 27 ++++++++++++++++++--------- 4 files changed, 47 insertions(+), 27 deletions(-) diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 96825604..1d83cec3 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs @@ -1,5 +1,7 @@ //! Generic SMI Ethernet PHY +use futures::task::Context; + use super::{StationManagement, PHY}; #[allow(dead_code)] @@ -40,13 +42,13 @@ pub struct GenericSMI; unsafe impl PHY for GenericSMI { /// Reset PHY and wait for it to come out of reset. - fn phy_reset(sm: &mut S) { + fn phy_reset(&mut self, sm: &mut S) { sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_RESET); while sm.smi_read(PHY_REG_BCR) & PHY_REG_BCR_RESET == PHY_REG_BCR_RESET {} } /// PHY initialisation. - fn phy_init(sm: &mut S) { + fn phy_init(&mut self, sm: &mut S) { // Clear WU CSR Self::smi_write_ext(sm, PHY_REG_WUCSR, 0); @@ -54,7 +56,9 @@ unsafe impl PHY for GenericSMI { sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M); } - fn poll_link(sm: &mut S) -> bool { + fn poll_link(&mut self, sm: &mut S, cx: &mut Context) -> bool { + cx.waker().wake_by_ref(); + let bsr = sm.smi_read(PHY_REG_BSR); // No link without autonegotiate diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 4989e17c..1687cb31 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs @@ -81,9 +81,7 @@ impl<'d, T: Instance, P: PHY> embassy_net_driver::Driver for Ethernet<'d, T, P> } fn link_state(&mut self, cx: &mut Context) -> LinkState { - // TODO: wake cx.waker on link state change - cx.waker().wake_by_ref(); - if P::poll_link(self) { + if self.phy.poll_link(&mut self.station_management, cx) { LinkState::Up } else { LinkState::Down @@ -148,11 +146,11 @@ pub unsafe trait StationManagement { /// The methods cannot move S pub unsafe trait PHY { /// Reset PHY and wait for it to come out of reset. - fn phy_reset(sm: &mut S); + fn phy_reset(&mut self, sm: &mut S); /// PHY initialisation. - fn phy_init(sm: &mut S); + fn phy_init(&mut self, sm: &mut S); /// Poll link to see if it is up and FD with 100Mbps - fn poll_link(sm: &mut S) -> bool; + fn poll_link(&mut self, sm: &mut S, cx: &mut Context) -> bool; } pub(crate) mod sealed { diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index b53c2d0f..2a6ea35f 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -3,6 +3,7 @@ mod rx_desc; mod tx_desc; +use core::marker::PhantomData; use core::sync::atomic::{fence, Ordering}; use embassy_hal_common::{into_ref, PeripheralRef}; @@ -48,9 +49,8 @@ pub struct Ethernet<'d, T: Instance, P: PHY> { pub(crate) rx: RDesRing<'d>, pins: [PeripheralRef<'d, AnyPin>; 9], - _phy: P, - clock_range: Cr, - phy_addr: u8, + pub(crate) phy: P, + pub(crate) station_management: EthernetStationManagement, pub(crate) mac_addr: [u8; 6], } @@ -224,9 +224,12 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { let mut this = Self { _peri: peri, pins, - _phy: phy, - clock_range, - phy_addr, + phy: phy, + station_management: EthernetStationManagement { + peri: PhantomData, + clock_range: clock_range, + phy_addr: phy_addr, + }, mac_addr, tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), @@ -256,8 +259,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { w.set_tie(true); }); - P::phy_reset(&mut this); - P::phy_init(&mut this); + this.phy.phy_reset(&mut this.station_management); + this.phy.phy_init(&mut this.station_management); interrupt::ETH.unpend(); unsafe { interrupt::ETH.enable() }; @@ -266,7 +269,13 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { } } -unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { +pub struct EthernetStationManagement { + peri: PhantomData, + clock_range: Cr, + phy_addr: u8, +} + +unsafe impl StationManagement for EthernetStationManagement { fn smi_read(&mut self, reg: u8) -> u16 { let mac = ETH.ethernet_mac(); diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 600e1d3b..bb681c42 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -1,5 +1,6 @@ mod descriptors; +use core::marker::PhantomData; use core::sync::atomic::{fence, Ordering}; use embassy_hal_common::{into_ref, PeripheralRef}; @@ -40,9 +41,8 @@ pub struct Ethernet<'d, T: Instance, P: PHY> { pub(crate) tx: TDesRing<'d>, pub(crate) rx: RDesRing<'d>, pins: [PeripheralRef<'d, AnyPin>; 9], - _phy: P, - clock_range: u8, - phy_addr: u8, + pub(crate) phy: P, + pub(crate) station_management: EthernetStationManagement, pub(crate) mac_addr: [u8; 6], } @@ -201,9 +201,12 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { tx: TDesRing::new(&mut queue.tx_desc, &mut queue.tx_buf), rx: RDesRing::new(&mut queue.rx_desc, &mut queue.rx_buf), pins, - _phy: phy, - clock_range, - phy_addr, + phy: phy, + station_management: EthernetStationManagement { + peri: PhantomData, + clock_range: clock_range, + phy_addr: phy_addr, + }, mac_addr, }; @@ -229,8 +232,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { w.set_tie(true); }); - P::phy_reset(&mut this); - P::phy_init(&mut this); + this.phy.phy_reset(&mut this.station_management); + this.phy.phy_init(&mut this.station_management); interrupt::ETH.unpend(); unsafe { interrupt::ETH.enable() }; @@ -239,7 +242,13 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { } } -unsafe impl<'d, T: Instance, P: PHY> StationManagement for Ethernet<'d, T, P> { +pub struct EthernetStationManagement { + peri: PhantomData, + clock_range: u8, + phy_addr: u8, +} + +unsafe impl StationManagement for EthernetStationManagement { fn smi_read(&mut self, reg: u8) -> u16 { let mac = ETH.ethernet_mac(); From bb24cfd1e8d359332acbc3c659cb9041d993483f Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 09:32:44 -0500 Subject: [PATCH 096/148] stm32/eth: add f4 example --- examples/stm32f4/src/bin/eth.rs | 111 ++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 examples/stm32f4/src/bin/eth.rs diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs new file mode 100644 index 00000000..c32d886d --- /dev/null +++ b/examples/stm32f4/src/bin/eth.rs @@ -0,0 +1,111 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_net::tcp::TcpSocket; +use embassy_net::{Ipv4Address, Stack, StackResources}; +use embassy_stm32::eth::generic_smi::GenericSMI; +use embassy_stm32::eth::{Ethernet, PacketQueue}; +use embassy_stm32::peripherals::ETH; +use embassy_stm32::rng::Rng; +use embassy_stm32::time::mhz; +use embassy_stm32::{bind_interrupts, eth, Config}; +use embassy_time::{Duration, Timer}; +use embedded_io::asynch::Write; +use static_cell::make_static; +use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + ETH => eth::InterruptHandler; +}); + +type Device = Ethernet<'static, ETH, GenericSMI>; + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) -> ! { + let mut config = Config::default(); + config.rcc.sys_ck = Some(mhz(200)); + let p = embassy_stm32::init(config); + + info!("Hello World!"); + + // Generate random seed. + let mut rng = Rng::new(p.RNG); + let mut seed = [0; 8]; + let _ = rng.async_fill_bytes(&mut seed).await; + let seed = u64::from_le_bytes(seed); + + let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; + + let device = Ethernet::new( + make_static!(PacketQueue::<16, 16>::new()), + p.ETH, + Irqs, + p.PA1, + p.PA2, + p.PC1, + p.PA7, + p.PC4, + p.PC5, + p.PG13, + p.PB13, + p.PG11, + GenericSMI, + mac_addr, + 0, + ); + + let config = embassy_net::Config::dhcpv4(Default::default()); + //let config = embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { + // address: Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), + // dns_servers: Vec::new(), + // gateway: Some(Ipv4Address::new(10, 42, 0, 1)), + //}); + + // Init network stack + let stack = &*make_static!(Stack::new( + device, + config, + make_static!(StackResources::<2>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Network task initialized"); + + // Then we can use it! + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [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))); + + let remote_endpoint = (Ipv4Address::new(10, 42, 0, 1), 8000); + info!("connecting..."); + let r = socket.connect(remote_endpoint).await; + if let Err(e) = r { + info!("connect error: {:?}", e); + continue; + } + info!("connected!"); + let buf = [0; 1024]; + loop { + let r = socket.write_all(&buf).await; + if let Err(e) = r { + info!("write error: {:?}", e); + continue; + } + Timer::after(Duration::from_secs(1)).await; + } + } +} From c3774607a55141ce55d8ba462a2ebe18f80056de Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 09:37:25 -0500 Subject: [PATCH 097/148] stm32/eth: convert static metho --- embassy-stm32/src/eth/generic_smi.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 1d83cec3..5c785643 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs @@ -50,7 +50,7 @@ unsafe impl PHY for GenericSMI { /// PHY initialisation. fn phy_init(&mut self, sm: &mut S) { // Clear WU CSR - Self::smi_write_ext(sm, PHY_REG_WUCSR, 0); + self.smi_write_ext(sm, PHY_REG_WUCSR, 0); // Enable auto-negotiation sm.smi_write(PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST | PHY_REG_BCR_100M); @@ -78,7 +78,7 @@ unsafe impl PHY for GenericSMI { /// Public functions for the PHY impl GenericSMI { // Writes a value to an extended PHY register in MMD address space - fn smi_write_ext(sm: &mut S, reg_addr: u16, reg_data: u16) { + fn smi_write_ext(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) { sm.smi_write(PHY_REG_CTL, 0x0003); // set address sm.smi_write(PHY_REG_ADDAR, reg_addr); sm.smi_write(PHY_REG_CTL, 0x4003); // set data From 975a780efe73b20d3ba63a116792b28f9a6edada Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 09:57:09 -0500 Subject: [PATCH 098/148] stm32/eth: impl. poll interval --- embassy-stm32/src/eth/generic_smi.rs | 25 ++++++++++++++++++++++++- examples/stm32f4/src/bin/eth.rs | 2 +- examples/stm32f7/src/bin/eth.rs | 2 +- examples/stm32h5/src/bin/eth.rs | 2 +- examples/stm32h7/src/bin/eth.rs | 2 +- examples/stm32h7/src/bin/eth_client.rs | 2 +- 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 5c785643..22631c2d 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs @@ -1,6 +1,10 @@ //! Generic SMI Ethernet PHY +#[cfg(feature = "time")] +use embassy_time::{Duration, Timer}; use futures::task::Context; +#[cfg(feature = "time")] +use futures::FutureExt; use super::{StationManagement, PHY}; @@ -38,7 +42,22 @@ mod phy_consts { use self::phy_consts::*; /// Generic SMI Ethernet PHY -pub struct GenericSMI; +pub struct GenericSMI { + #[cfg(feature = "time")] + poll_interval: Duration, +} + +impl GenericSMI { + #[cfg(feature = "time")] + pub fn new(poll_interval: Duration) -> Self { + Self { poll_interval } + } + + #[cfg(not(feature = "time"))] + pub fn new() -> Self { + Self {} + } +} unsafe impl PHY for GenericSMI { /// Reset PHY and wait for it to come out of reset. @@ -57,8 +76,12 @@ unsafe impl PHY for GenericSMI { } fn poll_link(&mut self, sm: &mut S, cx: &mut Context) -> bool { + #[cfg(not(feature = "time"))] cx.waker().wake_by_ref(); + #[cfg(feature = "time")] + let _ = Timer::after(self.poll_interval).poll_unpin(cx); + let bsr = sm.smi_read(PHY_REG_BSR); // No link without autonegotiate diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index c32d886d..15390592 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs @@ -56,7 +56,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI, + GenericSMI::new(Duration::from_millis(500)), mac_addr, 0, ); diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index fde6a757..c1baa584 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -57,7 +57,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI, + GenericSMI::new(Duration::from_millis(500)), mac_addr, 0, ); diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 78c8282a..3b33265a 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -76,7 +76,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB15, p.PG11, - GenericSMI, + GenericSMI::new(Duration::from_millis(500)), mac_addr, 0, ); diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 12d37f7a..9203708a 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -58,7 +58,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI, + GenericSMI::new(Duration::from_millis(500)), mac_addr, 0, ); diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 6078fc3f..8abc4109 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -59,7 +59,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI, + GenericSMI::new(Duration::from_millis(500)), mac_addr, 0, ); From 17d5e1c47046ea69ef7ac6041ae3cf3be587221b Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 12:02:08 -0500 Subject: [PATCH 099/148] stm32/eth: add set_poll_interval --- embassy-stm32/src/eth/generic_smi.rs | 10 ++++++++-- examples/stm32f4/src/bin/eth.rs | 2 +- examples/stm32f7/src/bin/eth.rs | 2 +- examples/stm32h5/src/bin/eth.rs | 2 +- examples/stm32h7/src/bin/eth.rs | 2 +- examples/stm32h7/src/bin/eth_client.rs | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 22631c2d..90631b17 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs @@ -49,8 +49,10 @@ pub struct GenericSMI { impl GenericSMI { #[cfg(feature = "time")] - pub fn new(poll_interval: Duration) -> Self { - Self { poll_interval } + pub fn new() -> Self { + Self { + poll_interval: Duration::from_millis(500), + } } #[cfg(not(feature = "time"))] @@ -100,6 +102,10 @@ unsafe impl PHY for GenericSMI { /// Public functions for the PHY impl GenericSMI { + pub fn set_poll_interval(&mut self, poll_interval: Duration) { + self.poll_interval = poll_interval + } + // Writes a value to an extended PHY register in MMD address space fn smi_write_ext(&mut self, sm: &mut S, reg_addr: u16, reg_data: u16) { sm.smi_write(PHY_REG_CTL, 0x0003); // set address diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index 15390592..d0b16439 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs @@ -56,7 +56,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI::new(Duration::from_millis(500)), + GenericSMI::new(), mac_addr, 0, ); diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index c1baa584..c6b2ba45 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -57,7 +57,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI::new(Duration::from_millis(500)), + GenericSMI::new(), mac_addr, 0, ); diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 3b33265a..0bff85ed 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -76,7 +76,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB15, p.PG11, - GenericSMI::new(Duration::from_millis(500)), + GenericSMI::new(), mac_addr, 0, ); diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 9203708a..cfafcaed 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -58,7 +58,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI::new(Duration::from_millis(500)), + GenericSMI::new(), mac_addr, 0, ); diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 8abc4109..4ed73757 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -59,7 +59,7 @@ async fn main(spawner: Spawner) -> ! { p.PG13, p.PB13, p.PG11, - GenericSMI::new(Duration::from_millis(500)), + GenericSMI::new(), mac_addr, 0, ); From d6dd5ea5d3ab7309bd5b4bec28afaee68d20b4ae Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 14:19:32 -0500 Subject: [PATCH 100/148] revert toolchain changes --- rust-toolchain.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index bad6d3a4..179ed1d6 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,8 +1,8 @@ # Before upgrading check that everything is available on all tier1 targets here: # https://rust-lang.github.io/rustup-components-history [toolchain] -channel = "nightly" -components = [ "rust-src", "rustfmt", "llvm-tools" ] +channel = "nightly-2023-06-28" +components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] targets = [ "thumbv7em-none-eabi", "thumbv7m-none-eabi", @@ -11,4 +11,4 @@ targets = [ "thumbv8m.main-none-eabihf", "riscv32imac-unknown-none-elf", "wasm32-unknown-unknown", -] +] \ No newline at end of file From d11a94e2a7c030dac7a7c4d6967f614104111d5a Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 14:28:42 -0500 Subject: [PATCH 101/148] wpan: add mac test --- tests/stm32/Cargo.toml | 20 ++-- tests/stm32/src/bin/rtc.rs | 2 + .../stm32/src/bin/{tl_mbox.rs => wpan_ble.rs} | 2 +- tests/stm32/src/bin/wpan_mac.rs | 108 ++++++++++++++++++ 4 files changed, 124 insertions(+), 8 deletions(-) rename tests/stm32/src/bin/{tl_mbox.rs => wpan_ble.rs} (99%) create mode 100644 tests/stm32/src/bin/wpan_mac.rs diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index d94bd730..b3a805e5 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -12,14 +12,15 @@ stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo -stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble" ] # Nucleo +stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "mac" ] # Nucleo stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board sdmmc = [] chrono = ["embassy-stm32/chrono", "dep:chrono"] can = [] -ble = ["dep:embassy-stm32-wpan"] +ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"] +mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"] not-gpdma = [] [dependencies] @@ -48,11 +49,6 @@ chrono = { version = "^0.4", default-features = false, optional = true} # BEGIN TESTS # Generated by gen_test.py. DO NOT EDIT. -[[bin]] -name = "tl_mbox" -path = "src/bin/tl_mbox.rs" -required-features = [ "ble",] - [[bin]] name = "can" path = "src/bin/can.rs" @@ -103,6 +99,16 @@ name = "usart_rx_ringbuffered" path = "src/bin/usart_rx_ringbuffered.rs" required-features = [ "not-gpdma",] +[[bin]] +name = "wpan_ble" +path = "src/bin/wpan_ble.rs" +required-features = [ "ble",] + +[[bin]] +name = "wpan_mac" +path = "src/bin/wpan_mac.rs" +required-features = [ "mac",] + # END TESTS [profile.dev] diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs index 582df575..194b153d 100644 --- a/tests/stm32/src/bin/rtc.rs +++ b/tests/stm32/src/bin/rtc.rs @@ -1,3 +1,5 @@ +// required-features: chrono + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/wpan_ble.rs similarity index 99% rename from tests/stm32/src/bin/tl_mbox.rs rename to tests/stm32/src/bin/wpan_ble.rs index af383270..3ad8aca4 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/wpan_ble.rs @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) { version_major, version_minor, subversion, sram2a_size, sram2b_size ); - mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; + let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; info!("resetting BLE..."); mbox.ble_subsystem.reset().await; diff --git a/tests/stm32/src/bin/wpan_mac.rs b/tests/stm32/src/bin/wpan_mac.rs new file mode 100644 index 00000000..d97a4d40 --- /dev/null +++ b/tests/stm32/src/bin/wpan_mac.rs @@ -0,0 +1,108 @@ +// required-features: mac + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +#[path = "../common.rs"] +mod common; + +use common::*; +use embassy_executor::Spawner; +use embassy_stm32::bind_interrupts; +use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, GetRequest, ResetRequest, SetRequest}; +use embassy_stm32_wpan::sub::mac::event::MacEvent; +use embassy_stm32_wpan::sub::mac::typedefs::{ + AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PanId, PibId, SecurityLevel, +}; +use embassy_stm32_wpan::sub::mm; +use embassy_stm32_wpan::TlMbox; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs{ + IPCC_C1_RX => ReceiveInterruptHandler; + IPCC_C1_TX => TransmitInterruptHandler; +}); + +#[embassy_executor::task] +async fn run_mm_queue(memory_manager: mm::MemoryManager) { + memory_manager.run_queue().await; +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_stm32::init(config()); + info!("Hello World!"); + + let config = Config::default(); + let mbox = TlMbox::init(p.IPCC, Irqs, config); + + spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + + let sys_event = mbox.sys_subsystem.read().await; + info!("sys event: {}", sys_event.payload()); + + core::mem::drop(sys_event); + + let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; + info!("initialized mac: {}", result); + + info!("resetting"); + mbox.mac_subsystem + .send_command(&ResetRequest { set_default_pib: true }) + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + + info!("setting extended address"); + let extended_address: u64 = 0xACDE480000000002; + mbox.mac_subsystem + .send_command(&SetRequest { + pib_attribute_ptr: &extended_address as *const _ as *const u8, + pib_attribute: PibId::ExtendedAddress, + }) + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + + info!("getting extended address"); + mbox.mac_subsystem + .send_command(&GetRequest { + pib_attribute: PibId::ExtendedAddress, + }) + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + + if let Ok(MacEvent::MlmeGetCnf(evt)) = evt { + if evt.pib_attribute_value_len == 8 { + let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; + + info!("value {:#x}", value) + } + } + + info!("assocation request"); + let a = AssociateRequest { + channel_number: MacChannel::Channel16, + channel_page: 0, + coord_addr_mode: AddressMode::Short, + coord_address: MacAddress { short: [34, 17] }, + capability_information: Capabilities::ALLOCATE_ADDRESS, + coord_pan_id: PanId([0x1A, 0xAA]), + security_level: SecurityLevel::Unsecure, + key_id_mode: KeyIdMode::Implicite, + key_source: [0; 8], + key_index: 152, + }; + info!("{}", a); + mbox.mac_subsystem.send_command(&a).await.unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} From 1f63fdbb15b2f8fb94167e12428901357de15c11 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 14:31:35 -0500 Subject: [PATCH 102/148] stm32/tests: fix cargo --- tests/stm32/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index b3a805e5..3007cd1e 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -21,6 +21,7 @@ chrono = ["embassy-stm32/chrono", "dep:chrono"] can = [] ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"] mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"] +embassy-stm32-wpan = [] not-gpdma = [] [dependencies] From 3705b4f40d206490a5165a287791206ac70573d9 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 14:38:02 -0500 Subject: [PATCH 103/148] rustfmt --- examples/stm32wb/src/bin/eddystone_beacon.rs | 2 +- examples/stm32wb/src/bin/gatt_server.rs | 2 +- examples/stm32wb/src/bin/tl_mbox_ble.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/stm32wb/src/bin/eddystone_beacon.rs b/examples/stm32wb/src/bin/eddystone_beacon.rs index b99f8cb2..451bd7d2 100644 --- a/examples/stm32wb/src/bin/eddystone_beacon.rs +++ b/examples/stm32wb/src/bin/eddystone_beacon.rs @@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) { let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); - mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; + let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; info!("resetting BLE..."); mbox.ble_subsystem.reset().await; diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs index 7621efb1..0f6419d4 100644 --- a/examples/stm32wb/src/bin/gatt_server.rs +++ b/examples/stm32wb/src/bin/gatt_server.rs @@ -71,7 +71,7 @@ async fn main(_spawner: Spawner) { let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); - mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; + let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; info!("resetting BLE..."); mbox.ble_subsystem.reset().await; diff --git a/examples/stm32wb/src/bin/tl_mbox_ble.rs b/examples/stm32wb/src/bin/tl_mbox_ble.rs index a511e89a..90349422 100644 --- a/examples/stm32wb/src/bin/tl_mbox_ble.rs +++ b/examples/stm32wb/src/bin/tl_mbox_ble.rs @@ -49,7 +49,7 @@ async fn main(_spawner: Spawner) { let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); - mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; + let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; info!("starting ble..."); mbox.ble_subsystem.tl_write(0x0c, &[]).await; From 4db4200c37c191f4ec018dd318e805aa805d9cc3 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 14:47:34 -0500 Subject: [PATCH 104/148] wpan: factor mac logic into other mod --- embassy-stm32-wpan/src/lib.rs | 3 +++ embassy-stm32-wpan/src/{sub => }/mac/commands.rs | 0 embassy-stm32-wpan/src/{sub => }/mac/consts.rs | 0 embassy-stm32-wpan/src/{sub => }/mac/event.rs | 2 +- embassy-stm32-wpan/src/{sub => }/mac/helpers.rs | 0 .../src/{sub => }/mac/indications.rs | 0 embassy-stm32-wpan/src/{sub => }/mac/macros.rs | 0 embassy-stm32-wpan/src/mac/mod.rs | 9 +++++++++ embassy-stm32-wpan/src/{sub => }/mac/opcodes.rs | 0 .../src/{sub => }/mac/responses.rs | 0 embassy-stm32-wpan/src/{sub => }/mac/typedefs.rs | 0 .../src/sub/{mac/mod.rs => mac.rs} | 16 +++------------- examples/stm32wb/src/bin/mac_ffd.rs | 6 +++--- examples/stm32wb/src/bin/mac_rfd.rs | 6 +++--- tests/stm32/src/bin/wpan_mac.rs | 6 +++--- 15 files changed, 25 insertions(+), 23 deletions(-) rename embassy-stm32-wpan/src/{sub => }/mac/commands.rs (100%) rename embassy-stm32-wpan/src/{sub => }/mac/consts.rs (100%) rename embassy-stm32-wpan/src/{sub => }/mac/event.rs (99%) rename embassy-stm32-wpan/src/{sub => }/mac/helpers.rs (100%) rename embassy-stm32-wpan/src/{sub => }/mac/indications.rs (100%) rename embassy-stm32-wpan/src/{sub => }/mac/macros.rs (100%) create mode 100644 embassy-stm32-wpan/src/mac/mod.rs rename embassy-stm32-wpan/src/{sub => }/mac/opcodes.rs (100%) rename embassy-stm32-wpan/src/{sub => }/mac/responses.rs (100%) rename embassy-stm32-wpan/src/{sub => }/mac/typedefs.rs (100%) rename embassy-stm32-wpan/src/sub/{mac/mod.rs => mac.rs} (94%) diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index 3a45c597..57f0dc4f 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -26,6 +26,9 @@ pub mod sub; pub mod tables; pub mod unsafe_linked_list; +#[cfg(feature = "mac")] +pub mod mac; + #[cfg(feature = "ble")] pub use crate::sub::ble::hci; diff --git a/embassy-stm32-wpan/src/sub/mac/commands.rs b/embassy-stm32-wpan/src/mac/commands.rs similarity index 100% rename from embassy-stm32-wpan/src/sub/mac/commands.rs rename to embassy-stm32-wpan/src/mac/commands.rs diff --git a/embassy-stm32-wpan/src/sub/mac/consts.rs b/embassy-stm32-wpan/src/mac/consts.rs similarity index 100% rename from embassy-stm32-wpan/src/sub/mac/consts.rs rename to embassy-stm32-wpan/src/mac/consts.rs diff --git a/embassy-stm32-wpan/src/sub/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs similarity index 99% rename from embassy-stm32-wpan/src/sub/mac/event.rs rename to embassy-stm32-wpan/src/mac/event.rs index aaf96556..dfce21fe 100644 --- a/embassy-stm32-wpan/src/sub/mac/event.rs +++ b/embassy-stm32-wpan/src/mac/event.rs @@ -7,7 +7,7 @@ use super::responses::{ AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm, PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm, }; -use crate::sub::mac::opcodes::OpcodeM0ToM4; +use crate::mac::opcodes::OpcodeM0ToM4; pub trait ParseableMacEvent { const SIZE: usize; diff --git a/embassy-stm32-wpan/src/sub/mac/helpers.rs b/embassy-stm32-wpan/src/mac/helpers.rs similarity index 100% rename from embassy-stm32-wpan/src/sub/mac/helpers.rs rename to embassy-stm32-wpan/src/mac/helpers.rs diff --git a/embassy-stm32-wpan/src/sub/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs similarity index 100% rename from embassy-stm32-wpan/src/sub/mac/indications.rs rename to embassy-stm32-wpan/src/mac/indications.rs diff --git a/embassy-stm32-wpan/src/sub/mac/macros.rs b/embassy-stm32-wpan/src/mac/macros.rs similarity index 100% rename from embassy-stm32-wpan/src/sub/mac/macros.rs rename to embassy-stm32-wpan/src/mac/macros.rs diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs new file mode 100644 index 00000000..1af8fe6b --- /dev/null +++ b/embassy-stm32-wpan/src/mac/mod.rs @@ -0,0 +1,9 @@ +pub mod commands; +mod consts; +pub mod event; +mod helpers; +pub mod indications; +mod macros; +mod opcodes; +pub mod responses; +pub mod typedefs; diff --git a/embassy-stm32-wpan/src/sub/mac/opcodes.rs b/embassy-stm32-wpan/src/mac/opcodes.rs similarity index 100% rename from embassy-stm32-wpan/src/sub/mac/opcodes.rs rename to embassy-stm32-wpan/src/mac/opcodes.rs diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/mac/responses.rs similarity index 100% rename from embassy-stm32-wpan/src/sub/mac/responses.rs rename to embassy-stm32-wpan/src/mac/responses.rs diff --git a/embassy-stm32-wpan/src/sub/mac/typedefs.rs b/embassy-stm32-wpan/src/mac/typedefs.rs similarity index 100% rename from embassy-stm32-wpan/src/sub/mac/typedefs.rs rename to embassy-stm32-wpan/src/mac/typedefs.rs diff --git a/embassy-stm32-wpan/src/sub/mac/mod.rs b/embassy-stm32-wpan/src/sub/mac.rs similarity index 94% rename from embassy-stm32-wpan/src/sub/mac/mod.rs rename to embassy-stm32-wpan/src/sub/mac.rs index ab39f89c..4893cb47 100644 --- a/embassy-stm32-wpan/src/sub/mac/mod.rs +++ b/embassy-stm32-wpan/src/sub/mac.rs @@ -8,25 +8,15 @@ use embassy_futures::poll_once; use embassy_stm32::ipcc::Ipcc; use embassy_sync::waitqueue::AtomicWaker; -use self::commands::MacCommand; -use self::event::MacEvent; -use self::typedefs::MacError; use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::{EvtBox, EvtPacket}; +use crate::mac::commands::MacCommand; +use crate::mac::event::MacEvent; +use crate::mac::typedefs::MacError; use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; use crate::{channels, evt}; -pub mod commands; -mod consts; -pub mod event; -mod helpers; -pub mod indications; -mod macros; -mod opcodes; -pub mod responses; -pub mod typedefs; - static MAC_WAKER: AtomicWaker = AtomicWaker::new(); static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false); diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 689a2835..e4d81997 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -6,9 +6,9 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::sub::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest}; -use embassy_stm32_wpan::sub::mac::event::MacEvent; -use embassy_stm32_wpan::sub::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel}; +use embassy_stm32_wpan::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest}; +use embassy_stm32_wpan::mac::event::MacEvent; +use embassy_stm32_wpan::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel}; use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index ea349f9a..b2dac72c 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -6,9 +6,9 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, DataRequest, GetRequest, ResetRequest, SetRequest}; -use embassy_stm32_wpan::sub::mac::event::MacEvent; -use embassy_stm32_wpan::sub::mac::typedefs::{ +use embassy_stm32_wpan::mac::commands::{AssociateRequest, DataRequest, GetRequest, ResetRequest, SetRequest}; +use embassy_stm32_wpan::mac::event::MacEvent; +use embassy_stm32_wpan::mac::typedefs::{ AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PanId, PibId, SecurityLevel, }; use embassy_stm32_wpan::sub::mm; diff --git a/tests/stm32/src/bin/wpan_mac.rs b/tests/stm32/src/bin/wpan_mac.rs index d97a4d40..cfa0aca3 100644 --- a/tests/stm32/src/bin/wpan_mac.rs +++ b/tests/stm32/src/bin/wpan_mac.rs @@ -10,9 +10,9 @@ use common::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, GetRequest, ResetRequest, SetRequest}; -use embassy_stm32_wpan::sub::mac::event::MacEvent; -use embassy_stm32_wpan::sub::mac::typedefs::{ +use embassy_stm32_wpan::mac::commands::{AssociateRequest, GetRequest, ResetRequest, SetRequest}; +use embassy_stm32_wpan::mac::event::MacEvent; +use embassy_stm32_wpan::mac::typedefs::{ AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PanId, PibId, SecurityLevel, }; use embassy_stm32_wpan::sub::mm; From 0b63af33135784c1410dc8667cfefbaa538a1f04 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 19:02:04 -0500 Subject: [PATCH 105/148] wpan: prepare net impl. --- embassy-net-driver/src/lib.rs | 3 +++ embassy-net/Cargo.toml | 1 + embassy-net/src/device.rs | 2 ++ embassy-net/src/lib.rs | 13 ++++++++++++- embassy-stm32-wpan/Cargo.toml | 3 ++- examples/stm32wb/Cargo.toml | 3 ++- 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/embassy-net-driver/src/lib.rs b/embassy-net-driver/src/lib.rs index 4149bf4a..09def20c 100644 --- a/embassy-net-driver/src/lib.rs +++ b/embassy-net-driver/src/lib.rs @@ -164,6 +164,9 @@ pub enum Medium { /// /// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode. Ip, + + /// IEEE 802_15_4 medium + Ieee802154, } impl Default for Medium { diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 6dc429dd..9b6a11c1 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml @@ -37,6 +37,7 @@ proto-ipv4 = ["smoltcp/proto-ipv4"] proto-ipv6 = ["smoltcp/proto-ipv6"] medium-ethernet = ["smoltcp/medium-ethernet"] medium-ip = ["smoltcp/medium-ip"] +medium-ieee802154 = ["smoltcp/medium-ieee802154"] igmp = ["smoltcp/proto-igmp"] [dependencies] diff --git a/embassy-net/src/device.rs b/embassy-net/src/device.rs index 4513c86d..d29ab897 100644 --- a/embassy-net/src/device.rs +++ b/embassy-net/src/device.rs @@ -51,6 +51,8 @@ where Medium::Ethernet => phy::Medium::Ethernet, #[cfg(feature = "medium-ip")] Medium::Ip => phy::Medium::Ip, + #[cfg(feature = "medium-ieee802154")] + Medium::Ieee802154 => phy::Medium::Ieee802154, #[allow(unreachable_patterns)] _ => panic!( "Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.", diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 0d0a986f..ad98d7f6 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -24,9 +24,11 @@ use embassy_net_driver::{Driver, LinkState, Medium}; use embassy_sync::waitqueue::WakerRegistration; use embassy_time::{Instant, Timer}; use futures::pin_mut; +#[allow(unused_imports)] use heapless::Vec; #[cfg(feature = "igmp")] pub use smoltcp::iface::MulticastError; +#[allow(unused_imports)] use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage}; #[cfg(feature = "dhcpv4")] use smoltcp::socket::dhcpv4::{self, RetryConfig}; @@ -34,6 +36,8 @@ use smoltcp::socket::dhcpv4::{self, RetryConfig}; pub use smoltcp::wire::IpListenEndpoint; #[cfg(feature = "medium-ethernet")] pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; +#[cfg(feature = "medium-ieee802154")] +pub use smoltcp::wire::{HardwareAddress, Ieee802154Address}; pub use smoltcp::wire::{IpAddress, IpCidr, IpEndpoint}; #[cfg(feature = "proto-ipv4")] pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr}; @@ -232,7 +236,7 @@ impl Stack { resources: &'static mut StackResources, random_seed: u64, ) -> Self { - #[cfg(feature = "medium-ethernet")] + #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] let medium = device.capabilities().medium; let hardware_addr = match medium { @@ -240,6 +244,8 @@ impl Stack { Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress(device.ethernet_address())), #[cfg(feature = "medium-ip")] Medium::Ip => HardwareAddress::Ip, + #[cfg(feature = "medium-ieee802154")] + Medium::Ieee802154 => HardwareAddress::Ieee802154(Ieee802154Address::Absent), #[allow(unreachable_patterns)] _ => panic!( "Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.", @@ -262,6 +268,7 @@ impl Stack { let next_local_port = (random_seed % (LOCAL_PORT_MAX - LOCAL_PORT_MIN) as u64) as u16 + LOCAL_PORT_MIN; + #[cfg_attr(feature = "medium-ieee802154", allow(unused_mut))] let mut socket = SocketStack { sockets, iface, @@ -269,6 +276,7 @@ impl Stack { next_local_port, }; + #[cfg_attr(feature = "medium-ieee802154", allow(unused_mut))] let mut inner = Inner { device, link_up: false, @@ -287,6 +295,9 @@ impl Stack { dns_waker: WakerRegistration::new(), }; + #[cfg(feature = "medium-ieee802154")] + let _ = config; + #[cfg(feature = "proto-ipv4")] match config.ipv4 { ConfigV4::Static(config) => { diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 868bffe7..082d00f1 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -17,6 +17,7 @@ embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } +embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel", optional=true } defmt = { version = "0.3", optional = true } cortex-m = "0.7.6" @@ -32,7 +33,7 @@ bitflags = { version = "2.3.3", optional = true } defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"] ble = ["dep:stm32wb-hci"] -mac = ["dep:bitflags"] +mac = ["dep:bitflags", "dep:embassy-net-driver-channel"] stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index becf2d3f..8585b99f 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -10,6 +10,7 @@ embassy-executor = { version = "0.2.0", path = "../../embassy-executor", feature embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } +embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ieee802154", "nightly"], optional=true } defmt = "0.3" defmt-rtt = "0.4" @@ -24,7 +25,7 @@ heapless = { version = "0.7.5", default-features = false } [features] default = ["ble", "mac"] -mac = ["embassy-stm32-wpan/mac"] +mac = ["embassy-stm32-wpan/mac", "dep:embassy-net"] ble = ["embassy-stm32-wpan/ble"] [[bin]] From cd592cb0550146158ea6f9d90ba8afe9e1b06a92 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 19:15:01 -0500 Subject: [PATCH 106/148] wpan: add files from cyw43 --- embassy-stm32-wpan/src/lib.rs | 3 +- embassy-stm32-wpan/src/mac/control.rs | 454 ++++++++++++++++++++++++ embassy-stm32-wpan/src/mac/driver.rs | 102 ++++++ embassy-stm32-wpan/src/mac/mod.rs | 92 +++++ embassy-stm32-wpan/src/mac/runner.rs | 489 ++++++++++++++++++++++++++ 5 files changed, 1139 insertions(+), 1 deletion(-) create mode 100644 embassy-stm32-wpan/src/mac/control.rs create mode 100644 embassy-stm32-wpan/src/mac/driver.rs create mode 100644 embassy-stm32-wpan/src/mac/runner.rs diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index 57f0dc4f..6836d7a8 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -1,5 +1,6 @@ #![no_std] -#![cfg_attr(feature = "ble", feature(async_fn_in_trait))] +#![cfg_attr(any(feature = "ble", feature = "mac"), feature(async_fn_in_trait))] +#![cfg_attr(feature = "mac", feature(type_alias_impl_trait, concat_bytes))] // This must go FIRST so that all the other modules see its macros. pub mod fmt; diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs new file mode 100644 index 00000000..c67614dd --- /dev/null +++ b/embassy-stm32-wpan/src/mac/control.rs @@ -0,0 +1,454 @@ +use core::cmp::{max, min}; + +use ch::driver::LinkState; +use embassy_net_driver_channel as ch; +use embassy_time::{Duration, Timer}; + +pub use crate::bus::SpiBusCyw43; +use crate::consts::*; +use crate::events::{Event, EventSubscriber, Events}; +use crate::fmt::Bytes; +use crate::ioctl::{IoctlState, IoctlType}; +use crate::structs::*; +use crate::{countries, events, PowerManagementMode}; + +#[derive(Debug)] +pub struct Error { + pub status: u32, +} + +pub struct Control<'a> { + state_ch: ch::StateRunner<'a>, + events: &'a Events, + ioctl_state: &'a IoctlState, +} + +impl<'a> Control<'a> { + pub(crate) fn new(state_ch: ch::StateRunner<'a>, event_sub: &'a Events, ioctl_state: &'a IoctlState) -> Self { + Self { + state_ch, + events: event_sub, + ioctl_state, + } + } + + pub async fn init(&mut self, clm: &[u8]) { + const CHUNK_SIZE: usize = 1024; + + debug!("Downloading CLM..."); + + let mut offs = 0; + for chunk in clm.chunks(CHUNK_SIZE) { + let mut flag = DOWNLOAD_FLAG_HANDLER_VER; + if offs == 0 { + flag |= DOWNLOAD_FLAG_BEGIN; + } + offs += chunk.len(); + if offs == clm.len() { + flag |= DOWNLOAD_FLAG_END; + } + + let header = DownloadHeader { + flag, + dload_type: DOWNLOAD_TYPE_CLM, + len: chunk.len() as _, + crc: 0, + }; + let mut buf = [0; 8 + 12 + CHUNK_SIZE]; + buf[0..8].copy_from_slice(b"clmload\x00"); + buf[8..20].copy_from_slice(&header.to_bytes()); + buf[20..][..chunk.len()].copy_from_slice(&chunk); + self.ioctl(IoctlType::Set, IOCTL_CMD_SET_VAR, 0, &mut buf[..8 + 12 + chunk.len()]) + .await; + } + + // check clmload ok + assert_eq!(self.get_iovar_u32("clmload_status").await, 0); + + debug!("Configuring misc stuff..."); + + // Disable tx gloming which transfers multiple packets in one request. + // 'glom' is short for "conglomerate" which means "gather together into + // a compact mass". + self.set_iovar_u32("bus:txglom", 0).await; + self.set_iovar_u32("apsta", 1).await; + + // read MAC addr. + let mut mac_addr = [0; 6]; + assert_eq!(self.get_iovar("cur_etheraddr", &mut mac_addr).await, 6); + debug!("mac addr: {:02x}", Bytes(&mac_addr)); + + let country = countries::WORLD_WIDE_XX; + let country_info = CountryInfo { + country_abbrev: [country.code[0], country.code[1], 0, 0], + country_code: [country.code[0], country.code[1], 0, 0], + rev: if country.rev == 0 { -1 } else { country.rev as _ }, + }; + self.set_iovar("country", &country_info.to_bytes()).await; + + // set country takes some time, next ioctls fail if we don't wait. + Timer::after(Duration::from_millis(100)).await; + + // Set antenna to chip antenna + self.ioctl_set_u32(IOCTL_CMD_ANTDIV, 0, 0).await; + + self.set_iovar_u32("bus:txglom", 0).await; + Timer::after(Duration::from_millis(100)).await; + //self.set_iovar_u32("apsta", 1).await; // this crashes, also we already did it before...?? + //Timer::after(Duration::from_millis(100)).await; + self.set_iovar_u32("ampdu_ba_wsize", 8).await; + Timer::after(Duration::from_millis(100)).await; + self.set_iovar_u32("ampdu_mpdu", 4).await; + Timer::after(Duration::from_millis(100)).await; + //self.set_iovar_u32("ampdu_rx_factor", 0).await; // this crashes + + //Timer::after(Duration::from_millis(100)).await; + + // evts + let mut evts = EventMask { + iface: 0, + events: [0xFF; 24], + }; + + // Disable spammy uninteresting events. + evts.unset(Event::RADIO); + evts.unset(Event::IF); + evts.unset(Event::PROBREQ_MSG); + evts.unset(Event::PROBREQ_MSG_RX); + evts.unset(Event::PROBRESP_MSG); + evts.unset(Event::PROBRESP_MSG); + evts.unset(Event::ROAM); + + self.set_iovar("bsscfg:event_msgs", &evts.to_bytes()).await; + + Timer::after(Duration::from_millis(100)).await; + + // set wifi up + self.ioctl(IoctlType::Set, IOCTL_CMD_UP, 0, &mut []).await; + + Timer::after(Duration::from_millis(100)).await; + + self.ioctl_set_u32(110, 0, 1).await; // SET_GMODE = auto + self.ioctl_set_u32(142, 0, 0).await; // SET_BAND = any + + Timer::after(Duration::from_millis(100)).await; + + self.state_ch.set_ethernet_address(mac_addr); + + debug!("INIT DONE"); + } + + pub async fn set_power_management(&mut self, mode: PowerManagementMode) { + // power save mode + let mode_num = mode.mode(); + if mode_num == 2 { + self.set_iovar_u32("pm2_sleep_ret", mode.sleep_ret_ms() as u32).await; + self.set_iovar_u32("bcn_li_bcn", mode.beacon_period() as u32).await; + self.set_iovar_u32("bcn_li_dtim", mode.dtim_period() as u32).await; + self.set_iovar_u32("assoc_listen", mode.assoc() as u32).await; + } + self.ioctl_set_u32(86, 0, mode_num).await; + } + + pub async fn join_open(&mut self, ssid: &str) -> Result<(), Error> { + self.set_iovar_u32("ampdu_ba_wsize", 8).await; + + self.ioctl_set_u32(134, 0, 0).await; // wsec = open + self.set_iovar_u32x2("bsscfg:sup_wpa", 0, 0).await; + self.ioctl_set_u32(20, 0, 1).await; // set_infra = 1 + self.ioctl_set_u32(22, 0, 0).await; // set_auth = open (0) + + let mut i = SsidInfo { + len: ssid.len() as _, + ssid: [0; 32], + }; + i.ssid[..ssid.len()].copy_from_slice(ssid.as_bytes()); + + self.wait_for_join(i).await + } + + pub async fn join_wpa2(&mut self, ssid: &str, passphrase: &str) -> Result<(), Error> { + self.set_iovar_u32("ampdu_ba_wsize", 8).await; + + self.ioctl_set_u32(134, 0, 4).await; // wsec = wpa2 + self.set_iovar_u32x2("bsscfg:sup_wpa", 0, 1).await; + self.set_iovar_u32x2("bsscfg:sup_wpa2_eapver", 0, 0xFFFF_FFFF).await; + self.set_iovar_u32x2("bsscfg:sup_wpa_tmo", 0, 2500).await; + + Timer::after(Duration::from_millis(100)).await; + + let mut pfi = PassphraseInfo { + len: passphrase.len() as _, + flags: 1, + passphrase: [0; 64], + }; + pfi.passphrase[..passphrase.len()].copy_from_slice(passphrase.as_bytes()); + self.ioctl(IoctlType::Set, IOCTL_CMD_SET_PASSPHRASE, 0, &mut pfi.to_bytes()) + .await; // WLC_SET_WSEC_PMK + + self.ioctl_set_u32(20, 0, 1).await; // set_infra = 1 + self.ioctl_set_u32(22, 0, 0).await; // set_auth = 0 (open) + self.ioctl_set_u32(165, 0, 0x80).await; // set_wpa_auth + + let mut i = SsidInfo { + len: ssid.len() as _, + ssid: [0; 32], + }; + i.ssid[..ssid.len()].copy_from_slice(ssid.as_bytes()); + + self.wait_for_join(i).await + } + + async fn wait_for_join(&mut self, i: SsidInfo) -> Result<(), Error> { + self.events.mask.enable(&[Event::SET_SSID, Event::AUTH]); + let mut subscriber = self.events.queue.subscriber().unwrap(); + // the actual join operation starts here + // we make sure to enable events before so we don't miss any + + // set_ssid + self.ioctl(IoctlType::Set, IOCTL_CMD_SET_SSID, 0, &mut i.to_bytes()) + .await; + + // to complete the join, we wait for a SET_SSID event + // we also save the AUTH status for the user, it may be interesting + let mut auth_status = 0; + let status = loop { + let msg = subscriber.next_message_pure().await; + if msg.header.event_type == Event::AUTH && msg.header.status != EStatus::SUCCESS { + auth_status = msg.header.status; + } else if msg.header.event_type == Event::SET_SSID { + // join operation ends with SET_SSID event + break msg.header.status; + } + }; + + self.events.mask.disable_all(); + if status == EStatus::SUCCESS { + // successful join + self.state_ch.set_link_state(LinkState::Up); + debug!("JOINED"); + Ok(()) + } else { + warn!("JOIN failed with status={} auth={}", status, auth_status); + Err(Error { status }) + } + } + + pub async fn gpio_set(&mut self, gpio_n: u8, gpio_en: bool) { + assert!(gpio_n < 3); + self.set_iovar_u32x2("gpioout", 1 << gpio_n, if gpio_en { 1 << gpio_n } else { 0 }) + .await + } + + pub async fn start_ap_open(&mut self, ssid: &str, channel: u8) { + self.start_ap(ssid, "", Security::OPEN, channel).await; + } + + pub async fn start_ap_wpa2(&mut self, ssid: &str, passphrase: &str, channel: u8) { + self.start_ap(ssid, passphrase, Security::WPA2_AES_PSK, channel).await; + } + + async fn start_ap(&mut self, ssid: &str, passphrase: &str, security: Security, channel: u8) { + if security != Security::OPEN + && (passphrase.as_bytes().len() < MIN_PSK_LEN || passphrase.as_bytes().len() > MAX_PSK_LEN) + { + panic!("Passphrase is too short or too long"); + } + + // Temporarily set wifi down + self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).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; + + // Turn on AP mode + self.ioctl_set_u32(IOCTL_CMD_SET_AP, 0, 1).await; + + // Set SSID + let mut i = SsidInfoWithIndex { + index: 0, + ssid_info: SsidInfo { + len: ssid.as_bytes().len() as _, + ssid: [0; 32], + }, + }; + i.ssid_info.ssid[..ssid.as_bytes().len()].copy_from_slice(ssid.as_bytes()); + self.set_iovar("bsscfg:ssid", &i.to_bytes()).await; + + // Set channel number + self.ioctl_set_u32(IOCTL_CMD_SET_CHANNEL, 0, channel as u32).await; + + // Set security + self.set_iovar_u32x2("bsscfg:wsec", 0, (security as u32) & 0xFF).await; + + if security != Security::OPEN { + self.set_iovar_u32x2("bsscfg:wpa_auth", 0, 0x0084).await; // wpa_auth = WPA2_AUTH_PSK | WPA_AUTH_PSK + + Timer::after(Duration::from_millis(100)).await; + + // Set passphrase + let mut pfi = PassphraseInfo { + len: passphrase.as_bytes().len() as _, + flags: 1, // WSEC_PASSPHRASE + passphrase: [0; 64], + }; + pfi.passphrase[..passphrase.as_bytes().len()].copy_from_slice(passphrase.as_bytes()); + self.ioctl(IoctlType::Set, IOCTL_CMD_SET_PASSPHRASE, 0, &mut pfi.to_bytes()) + .await; + } + + // Change mutlicast rate from 1 Mbps to 11 Mbps + self.set_iovar_u32("2g_mrate", 11000000 / 500000).await; + + // Start AP + self.set_iovar_u32x2("bss", 0, 1).await; // bss = BSS_UP + } + + async fn set_iovar_u32x2(&mut self, name: &str, val1: u32, val2: u32) { + let mut buf = [0; 8]; + buf[0..4].copy_from_slice(&val1.to_le_bytes()); + buf[4..8].copy_from_slice(&val2.to_le_bytes()); + self.set_iovar(name, &buf).await + } + + async fn set_iovar_u32(&mut self, name: &str, val: u32) { + self.set_iovar(name, &val.to_le_bytes()).await + } + + async fn get_iovar_u32(&mut self, name: &str) -> u32 { + let mut buf = [0; 4]; + let len = self.get_iovar(name, &mut buf).await; + assert_eq!(len, 4); + u32::from_le_bytes(buf) + } + + async fn set_iovar(&mut self, name: &str, val: &[u8]) { + self.set_iovar_v::<64>(name, val).await + } + + async fn set_iovar_v(&mut self, name: &str, val: &[u8]) { + debug!("set {} = {:02x}", name, Bytes(val)); + + let mut buf = [0; BUFSIZE]; + buf[..name.len()].copy_from_slice(name.as_bytes()); + buf[name.len()] = 0; + buf[name.len() + 1..][..val.len()].copy_from_slice(val); + + let total_len = name.len() + 1 + val.len(); + self.ioctl(IoctlType::Set, IOCTL_CMD_SET_VAR, 0, &mut buf[..total_len]) + .await; + } + + // TODO this is not really working, it always returns all zeros. + async fn get_iovar(&mut self, name: &str, res: &mut [u8]) -> usize { + debug!("get {}", name); + + let mut buf = [0; 64]; + buf[..name.len()].copy_from_slice(name.as_bytes()); + buf[name.len()] = 0; + + let total_len = max(name.len() + 1, res.len()); + let res_len = self + .ioctl(IoctlType::Get, IOCTL_CMD_GET_VAR, 0, &mut buf[..total_len]) + .await; + + let out_len = min(res.len(), res_len); + res[..out_len].copy_from_slice(&buf[..out_len]); + out_len + } + + async fn ioctl_set_u32(&mut self, cmd: u32, iface: u32, val: u32) { + let mut buf = val.to_le_bytes(); + self.ioctl(IoctlType::Set, cmd, iface, &mut buf).await; + } + + async fn ioctl(&mut self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize { + struct CancelOnDrop<'a>(&'a IoctlState); + + impl CancelOnDrop<'_> { + fn defuse(self) { + core::mem::forget(self); + } + } + + impl Drop for CancelOnDrop<'_> { + fn drop(&mut self) { + self.0.cancel_ioctl(); + } + } + + let ioctl = CancelOnDrop(self.ioctl_state); + let resp_len = ioctl.0.do_ioctl(kind, cmd, iface, buf).await; + ioctl.defuse(); + + resp_len + } + + /// Start a wifi scan + /// + /// Returns a `Stream` of networks found by the device + /// + /// # Note + /// Device events are currently implemented using a bounded queue. + /// To not miss any events, you should make sure to always await the stream. + pub async fn scan(&mut self) -> Scanner<'_> { + const SCANTYPE_PASSIVE: u8 = 1; + + let scan_params = ScanParams { + version: 1, + action: 1, + sync_id: 1, + ssid_len: 0, + ssid: [0; 32], + bssid: [0xff; 6], + bss_type: 2, + scan_type: SCANTYPE_PASSIVE, + nprobes: !0, + active_time: !0, + passive_time: !0, + home_time: !0, + channel_num: 0, + channel_list: [0; 1], + }; + + self.events.mask.enable(&[Event::ESCAN_RESULT]); + let subscriber = self.events.queue.subscriber().unwrap(); + self.set_iovar_v::<256>("escan", &scan_params.to_bytes()).await; + + Scanner { + subscriber, + events: &self.events, + } + } +} + +pub struct Scanner<'a> { + subscriber: EventSubscriber<'a>, + events: &'a Events, +} + +impl Scanner<'_> { + /// wait for the next found network + pub async fn next(&mut self) -> Option { + let event = self.subscriber.next_message_pure().await; + if event.header.status != EStatus::PARTIAL { + self.events.mask.disable_all(); + return None; + } + + if let events::Payload::BssInfo(bss) = event.payload { + Some(bss) + } else { + None + } + } +} + +impl Drop for Scanner<'_> { + fn drop(&mut self) { + self.events.mask.disable_all(); + } +} diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs new file mode 100644 index 00000000..3171d61f --- /dev/null +++ b/embassy-stm32-wpan/src/mac/driver.rs @@ -0,0 +1,102 @@ +#![no_std] +#![no_main] +#![allow(incomplete_features)] +#![feature(async_fn_in_trait, type_alias_impl_trait, concat_bytes)] +#![deny(unused_must_use)] + +use core::slice; + +use embassy_net_driver_channel as ch; +use embedded_hal_1::digital::OutputPin; +use events::Events; +use ioctl::IoctlState; + +use crate::bus::Bus; +pub use crate::bus::SpiBusCyw43; +pub use crate::control::{Control, Error as ControlError}; +pub use crate::runner::Runner; +pub use crate::structs::BssInfo; + +const MTU: usize = 1514; + +pub struct State { + ioctl_state: IoctlState, + ch: ch::State, + events: Events, +} + +impl State { + pub fn new() -> Self { + Self { + ioctl_state: IoctlState::new(), + ch: ch::State::new(), + events: Events::new(), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum PowerManagementMode { + /// Custom, officially unsupported mode. Use at your own risk. + /// All power-saving features set to their max at only a marginal decrease in power consumption + /// as oppposed to `Aggressive`. + SuperSave, + + /// Aggressive power saving mode. + Aggressive, + + /// The default mode. + PowerSave, + + /// Performance is prefered over power consumption but still some power is conserved as opposed to + /// `None`. + Performance, + + /// Unlike all the other PM modes, this lowers the power consumption at all times at the cost of + /// a much lower throughput. + ThroughputThrottling, + + /// No power management is configured. This consumes the most power. + None, +} + +impl Default for PowerManagementMode { + fn default() -> Self { + Self::PowerSave + } +} + +impl PowerManagementMode { + // TODO +} + +pub type NetDriver<'a> = ch::Device<'a, MTU>; + +pub async fn new<'a, PWR, SPI>( + state: &'a mut State, + pwr: PWR, + spi: SPI, + firmware: &[u8], +) -> (NetDriver<'a>, Control<'a>, Runner<'a, PWR, SPI>) +where + PWR: OutputPin, + SPI: SpiBusCyw43, +{ + let (ch_runner, device) = ch::new(&mut state.ch, [0; 6]); + let state_ch = ch_runner.state_runner(); + + let mut runner = Runner::new(ch_runner, Bus::new(pwr, spi), &state.ioctl_state, &state.events); + + runner.init(firmware).await; + + ( + device, + Control::new(state_ch, &state.events, &state.ioctl_state), + runner, + ) +} + +fn slice8_mut(x: &mut [u32]) -> &mut [u8] { + let len = x.len() * 4; + unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) } +} diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs index 1af8fe6b..e27f0ba7 100644 --- a/embassy-stm32-wpan/src/mac/mod.rs +++ b/embassy-stm32-wpan/src/mac/mod.rs @@ -1,9 +1,101 @@ pub mod commands; mod consts; +pub mod control; pub mod event; mod helpers; pub mod indications; mod macros; mod opcodes; pub mod responses; +pub mod runner; pub mod typedefs; + +use core::slice; + +use embassy_net_driver_channel as ch; + +use crate::bus::Bus; +pub use crate::bus::SpiBusCyw43; +pub use crate::mac::control::{Control, Error as ControlError}; +pub use crate::runner::Runner; +pub use crate::structs::BssInfo; +use crate::sub::mac::Mac; + +const MTU: usize = 1514; + +pub struct State { + ioctl_state: IoctlState, + ch: ch::State, + events: Events, +} + +impl State { + pub fn new() -> Self { + Self { + ioctl_state: IoctlState::new(), + ch: ch::State::new(), + events: Events::new(), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum PowerManagementMode { + /// Custom, officially unsupported mode. Use at your own risk. + /// All power-saving features set to their max at only a marginal decrease in power consumption + /// as oppposed to `Aggressive`. + SuperSave, + + /// Aggressive power saving mode. + Aggressive, + + /// The default mode. + PowerSave, + + /// Performance is prefered over power consumption but still some power is conserved as opposed to + /// `None`. + Performance, + + /// Unlike all the other PM modes, this lowers the power consumption at all times at the cost of + /// a much lower throughput. + ThroughputThrottling, + + /// No power management is configured. This consumes the most power. + None, +} + +impl Default for PowerManagementMode { + fn default() -> Self { + Self::PowerSave + } +} + +impl PowerManagementMode { + // TODO +} + +pub type NetDriver<'a> = ch::Device<'a, MTU>; + +pub async fn new<'a, PWR, SPI>( + state: &'a mut State, + mac_subsystem: Mac, + firmware: &[u8], +) -> (NetDriver<'a>, Control<'a>, Runner<'a, PWR, SPI>) { + let (ch_runner, device) = ch::new(&mut state.ch, [0; 6]); + let state_ch = ch_runner.state_runner(); + + let mut runner = Runner::new(ch_runner, Bus::new(pwr, spi), &state.ioctl_state, &state.events); + + runner.init(firmware).await; + + ( + device, + Control::new(state_ch, &state.events, &state.ioctl_state), + runner, + ) +} + +fn slice8_mut(x: &mut [u32]) -> &mut [u8] { + let len = x.len() * 4; + unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) } +} diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs new file mode 100644 index 00000000..7f0bbd67 --- /dev/null +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -0,0 +1,489 @@ +use embassy_futures::select::{select3, Either3}; +use embassy_net_driver_channel as ch; +use embassy_sync::pubsub::PubSubBehavior; + +use crate::sub::mac::Mac; + +#[cfg(feature = "firmware-logs")] +struct LogState { + addr: u32, + last_idx: usize, + buf: [u8; 256], + buf_count: usize, +} + +#[cfg(feature = "firmware-logs")] +impl Default for LogState { + fn default() -> Self { + Self { + addr: Default::default(), + last_idx: Default::default(), + buf: [0; 256], + buf_count: Default::default(), + } + } +} + +pub struct Runner<'a, PWR, SPI> { + ch: ch::Runner<'a, MTU>, + mac: Mac, + + ioctl_state: &'a IoctlState, + ioctl_id: u16, + sdpcm_seq: u8, + sdpcm_seq_max: u8, + + events: &'a Events, + + #[cfg(feature = "firmware-logs")] + log: LogState, +} + +impl<'a, PWR, SPI> Runner<'a, PWR, SPI> +where + PWR: OutputPin, + SPI: SpiBusCyw43, +{ + pub(crate) fn new( + ch: ch::Runner<'a, MTU>, + bus: Bus, + ioctl_state: &'a IoctlState, + events: &'a Events, + ) -> Self { + Self { + ch, + bus, + ioctl_state, + ioctl_id: 0, + sdpcm_seq: 0, + sdpcm_seq_max: 1, + events, + #[cfg(feature = "firmware-logs")] + log: LogState::default(), + } + } + + pub(crate) async fn init(&mut self, firmware: &[u8]) { + self.bus.init().await; + + #[cfg(feature = "firmware-logs")] + self.log_init().await; + + debug!("wifi init done"); + } + + #[cfg(feature = "firmware-logs")] + async fn log_init(&mut self) { + // Initialize shared memory for logging. + + let addr = CHIP.atcm_ram_base_address + CHIP.chip_ram_size - 4 - CHIP.socram_srmem_size; + let shared_addr = self.bus.bp_read32(addr).await; + debug!("shared_addr {:08x}", shared_addr); + + let mut shared = [0; SharedMemData::SIZE]; + self.bus.bp_read(shared_addr, &mut shared).await; + let shared = SharedMemData::from_bytes(&shared); + + self.log.addr = shared.console_addr + 8; + } + + #[cfg(feature = "firmware-logs")] + async fn log_read(&mut self) { + // Read log struct + let mut log = [0; SharedMemLog::SIZE]; + self.bus.bp_read(self.log.addr, &mut log).await; + let log = SharedMemLog::from_bytes(&log); + + let idx = log.idx as usize; + + // If pointer hasn't moved, no need to do anything. + if idx == self.log.last_idx { + return; + } + + // Read entire buf for now. We could read only what we need, but then we + // run into annoying alignment issues in `bp_read`. + let mut buf = [0; 0x400]; + self.bus.bp_read(log.buf, &mut buf).await; + + while self.log.last_idx != idx as usize { + let b = buf[self.log.last_idx]; + if b == b'\r' || b == b'\n' { + if self.log.buf_count != 0 { + let s = unsafe { core::str::from_utf8_unchecked(&self.log.buf[..self.log.buf_count]) }; + debug!("LOGS: {}", s); + self.log.buf_count = 0; + } + } else if self.log.buf_count < self.log.buf.len() { + self.log.buf[self.log.buf_count] = b; + self.log.buf_count += 1; + } + + self.log.last_idx += 1; + if self.log.last_idx == 0x400 { + self.log.last_idx = 0; + } + } + } + + pub async fn run(mut self) -> ! { + let mut buf = [0; 512]; + loop { + #[cfg(feature = "firmware-logs")] + self.log_read().await; + + if self.has_credit() { + let ioctl = self.ioctl_state.wait_pending(); + let tx = self.ch.tx_buf(); + let ev = self.bus.wait_for_event(); + + match select3(ioctl, tx, ev).await { + Either3::First(PendingIoctl { + buf: iobuf, + kind, + cmd, + iface, + }) => { + self.send_ioctl(kind, cmd, iface, unsafe { &*iobuf }).await; + self.check_status(&mut buf).await; + } + Either3::Second(packet) => { + trace!("tx pkt {:02x}", Bytes(&packet[..packet.len().min(48)])); + + let mut buf = [0; 512]; + let buf8 = slice8_mut(&mut buf); + + // There MUST be 2 bytes of padding between the SDPCM and BDC headers. + // And ONLY for data packets! + // No idea why, but the firmware will append two zero bytes to the tx'd packets + // otherwise. If the packet is exactly 1514 bytes (the max MTU), this makes it + // be oversized and get dropped. + // WHD adds it here https://github.com/Infineon/wifi-host-driver/blob/c04fcbb6b0d049304f376cf483fd7b1b570c8cd5/WiFi_Host_Driver/src/include/whd_sdpcm.h#L90 + // and adds it to the header size her https://github.com/Infineon/wifi-host-driver/blob/c04fcbb6b0d049304f376cf483fd7b1b570c8cd5/WiFi_Host_Driver/src/whd_sdpcm.c#L597 + // ¯\_(ツ)_/¯ + const PADDING_SIZE: usize = 2; + let total_len = SdpcmHeader::SIZE + PADDING_SIZE + BdcHeader::SIZE + packet.len(); + + let seq = self.sdpcm_seq; + self.sdpcm_seq = self.sdpcm_seq.wrapping_add(1); + + let sdpcm_header = SdpcmHeader { + len: total_len as u16, // TODO does this len need to be rounded up to u32? + len_inv: !total_len as u16, + sequence: seq, + channel_and_flags: CHANNEL_TYPE_DATA, + next_length: 0, + header_length: (SdpcmHeader::SIZE + PADDING_SIZE) as _, + wireless_flow_control: 0, + bus_data_credit: 0, + reserved: [0, 0], + }; + + let bdc_header = BdcHeader { + flags: BDC_VERSION << BDC_VERSION_SHIFT, + priority: 0, + flags2: 0, + data_offset: 0, + }; + trace!("tx {:?}", sdpcm_header); + trace!(" {:?}", bdc_header); + + buf8[0..SdpcmHeader::SIZE].copy_from_slice(&sdpcm_header.to_bytes()); + buf8[SdpcmHeader::SIZE + PADDING_SIZE..][..BdcHeader::SIZE] + .copy_from_slice(&bdc_header.to_bytes()); + buf8[SdpcmHeader::SIZE + PADDING_SIZE + BdcHeader::SIZE..][..packet.len()] + .copy_from_slice(packet); + + let total_len = (total_len + 3) & !3; // round up to 4byte + + trace!(" {:02x}", Bytes(&buf8[..total_len.min(48)])); + + self.bus.wlan_write(&buf[..(total_len / 4)]).await; + self.ch.tx_done(); + self.check_status(&mut buf).await; + } + Either3::Third(()) => { + self.handle_irq(&mut buf).await; + } + } + } else { + warn!("TX stalled"); + self.bus.wait_for_event().await; + self.handle_irq(&mut buf).await; + } + } + } + + /// Wait for IRQ on F2 packet available + async fn handle_irq(&mut self, buf: &mut [u32; 512]) { + // Receive stuff + let irq = self.bus.read16(FUNC_BUS, REG_BUS_INTERRUPT).await; + trace!("irq{}", FormatInterrupt(irq)); + + if irq & IRQ_F2_PACKET_AVAILABLE != 0 { + self.check_status(buf).await; + } + + if irq & IRQ_DATA_UNAVAILABLE != 0 { + // TODO what should we do here? + warn!("IRQ DATA_UNAVAILABLE, clearing..."); + self.bus.write16(FUNC_BUS, REG_BUS_INTERRUPT, 1).await; + } + } + + /// Handle F2 events while status register is set + async fn check_status(&mut self, buf: &mut [u32; 512]) { + loop { + let status = self.bus.status(); + trace!("check status{}", FormatStatus(status)); + + if status & STATUS_F2_PKT_AVAILABLE != 0 { + let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT; + self.bus.wlan_read(buf, len).await; + trace!("rx {:02x}", Bytes(&slice8_mut(buf)[..(len as usize).min(48)])); + self.rx(&mut slice8_mut(buf)[..len as usize]); + } else { + break; + } + } + } + + fn rx(&mut self, packet: &mut [u8]) { + let Some((sdpcm_header, payload)) = SdpcmHeader::parse(packet) else { + return; + }; + + self.update_credit(&sdpcm_header); + + let channel = sdpcm_header.channel_and_flags & 0x0f; + + match channel { + CHANNEL_TYPE_CONTROL => { + let Some((cdc_header, response)) = CdcHeader::parse(payload) else { + return; + }; + trace!(" {:?}", cdc_header); + + if cdc_header.id == self.ioctl_id { + if cdc_header.status != 0 { + // TODO: propagate error instead + panic!("IOCTL error {}", cdc_header.status as i32); + } + + self.ioctl_state.ioctl_done(response); + } + } + CHANNEL_TYPE_EVENT => { + let Some((_, bdc_packet)) = BdcHeader::parse(payload) else { + warn!("BDC event, incomplete header"); + return; + }; + + let Some((event_packet, evt_data)) = EventPacket::parse(bdc_packet) else { + warn!("BDC event, incomplete data"); + return; + }; + + const ETH_P_LINK_CTL: u16 = 0x886c; // HPNA, wlan link local tunnel, according to linux if_ether.h + if event_packet.eth.ether_type != ETH_P_LINK_CTL { + warn!( + "unexpected ethernet type 0x{:04x}, expected Broadcom ether type 0x{:04x}", + event_packet.eth.ether_type, ETH_P_LINK_CTL + ); + return; + } + const BROADCOM_OUI: &[u8] = &[0x00, 0x10, 0x18]; + if event_packet.hdr.oui != BROADCOM_OUI { + warn!( + "unexpected ethernet OUI {:02x}, expected Broadcom OUI {:02x}", + Bytes(&event_packet.hdr.oui), + Bytes(BROADCOM_OUI) + ); + return; + } + const BCMILCP_SUBTYPE_VENDOR_LONG: u16 = 32769; + if event_packet.hdr.subtype != BCMILCP_SUBTYPE_VENDOR_LONG { + warn!("unexpected subtype {}", event_packet.hdr.subtype); + return; + } + + const BCMILCP_BCM_SUBTYPE_EVENT: u16 = 1; + if event_packet.hdr.user_subtype != BCMILCP_BCM_SUBTYPE_EVENT { + warn!("unexpected user_subtype {}", event_packet.hdr.subtype); + return; + } + + let evt_type = events::Event::from(event_packet.msg.event_type as u8); + debug!( + "=== EVENT {:?}: {:?} {:02x}", + evt_type, + event_packet.msg, + Bytes(evt_data) + ); + + if self.events.mask.is_enabled(evt_type) { + let status = event_packet.msg.status; + let event_payload = match evt_type { + Event::ESCAN_RESULT if status == EStatus::PARTIAL => { + let Some((_, bss_info)) = ScanResults::parse(evt_data) else { + return; + }; + let Some(bss_info) = BssInfo::parse(bss_info) else { + return; + }; + events::Payload::BssInfo(*bss_info) + } + Event::ESCAN_RESULT => events::Payload::None, + _ => events::Payload::None, + }; + + // this intentionally uses the non-blocking publish immediate + // publish() is a deadlock risk in the current design as awaiting here prevents ioctls + // The `Runner` always yields when accessing the device, so consumers always have a chance to receive the event + // (if they are actively awaiting the queue) + self.events.queue.publish_immediate(events::Message::new( + Status { + event_type: evt_type, + status, + }, + event_payload, + )); + } + } + CHANNEL_TYPE_DATA => { + let Some((_, packet)) = BdcHeader::parse(payload) else { + return; + }; + trace!("rx pkt {:02x}", Bytes(&packet[..packet.len().min(48)])); + + match self.ch.try_rx_buf() { + Some(buf) => { + buf[..packet.len()].copy_from_slice(packet); + self.ch.rx_done(packet.len()) + } + None => warn!("failed to push rxd packet to the channel."), + } + } + _ => {} + } + } + + fn update_credit(&mut self, sdpcm_header: &SdpcmHeader) { + if sdpcm_header.channel_and_flags & 0xf < 3 { + let mut sdpcm_seq_max = sdpcm_header.bus_data_credit; + if sdpcm_seq_max.wrapping_sub(self.sdpcm_seq) > 0x40 { + sdpcm_seq_max = self.sdpcm_seq + 2; + } + self.sdpcm_seq_max = sdpcm_seq_max; + } + } + + fn has_credit(&self) -> bool { + self.sdpcm_seq != self.sdpcm_seq_max && self.sdpcm_seq_max.wrapping_sub(self.sdpcm_seq) & 0x80 == 0 + } + + async fn send_ioctl(&mut self, kind: IoctlType, cmd: u32, iface: u32, data: &[u8]) { + let mut buf = [0; 512]; + let buf8 = slice8_mut(&mut buf); + + let total_len = SdpcmHeader::SIZE + CdcHeader::SIZE + data.len(); + + let sdpcm_seq = self.sdpcm_seq; + self.sdpcm_seq = self.sdpcm_seq.wrapping_add(1); + self.ioctl_id = self.ioctl_id.wrapping_add(1); + + let sdpcm_header = SdpcmHeader { + len: total_len as u16, // TODO does this len need to be rounded up to u32? + len_inv: !total_len as u16, + sequence: sdpcm_seq, + channel_and_flags: CHANNEL_TYPE_CONTROL, + next_length: 0, + header_length: SdpcmHeader::SIZE as _, + wireless_flow_control: 0, + bus_data_credit: 0, + reserved: [0, 0], + }; + + let cdc_header = CdcHeader { + cmd: cmd, + len: data.len() as _, + flags: kind as u16 | (iface as u16) << 12, + id: self.ioctl_id, + status: 0, + }; + trace!("tx {:?}", sdpcm_header); + trace!(" {:?}", cdc_header); + + buf8[0..SdpcmHeader::SIZE].copy_from_slice(&sdpcm_header.to_bytes()); + buf8[SdpcmHeader::SIZE..][..CdcHeader::SIZE].copy_from_slice(&cdc_header.to_bytes()); + buf8[SdpcmHeader::SIZE + CdcHeader::SIZE..][..data.len()].copy_from_slice(data); + + let total_len = (total_len + 3) & !3; // round up to 4byte + + trace!(" {:02x}", Bytes(&buf8[..total_len.min(48)])); + + self.bus.wlan_write(&buf[..total_len / 4]).await; + } + + async fn core_disable(&mut self, core: Core) { + let base = core.base_addr(); + + // Dummy read? + let _ = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; + + // Check it isn't already reset + let r = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; + if r & AI_RESETCTRL_BIT_RESET != 0 { + return; + } + + self.bus.bp_write8(base + AI_IOCTRL_OFFSET, 0).await; + let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; + + block_for(Duration::from_millis(1)); + + self.bus + .bp_write8(base + AI_RESETCTRL_OFFSET, AI_RESETCTRL_BIT_RESET) + .await; + let _ = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; + } + + async fn core_reset(&mut self, core: Core) { + self.core_disable(core).await; + + let base = core.base_addr(); + self.bus + .bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN) + .await; + let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; + + self.bus.bp_write8(base + AI_RESETCTRL_OFFSET, 0).await; + + Timer::after(Duration::from_millis(1)).await; + + self.bus + .bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_CLOCK_EN) + .await; + let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; + + Timer::after(Duration::from_millis(1)).await; + } + + async fn core_is_up(&mut self, core: Core) -> bool { + let base = core.base_addr(); + + let io = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; + if io & (AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN) != AI_IOCTRL_BIT_CLOCK_EN { + debug!("core_is_up: returning false due to bad ioctrl {:02x}", io); + return false; + } + + let r = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; + if r & (AI_RESETCTRL_BIT_RESET) != 0 { + debug!("core_is_up: returning false due to bad resetctrl {:02x}", r); + return false; + } + + true + } +} From 88d1976e812af995028025407872bf64264c4f94 Mon Sep 17 00:00:00 2001 From: maximedeboeck <119764381+maximedeboeck@users.noreply.github.com> Date: Sun, 16 Jul 2023 12:31:56 +0200 Subject: [PATCH 107/148] Added usb-hid keyboard example for rp pico. --- examples/rp/Cargo.toml | 1 + examples/rp/src/bin/usb_hid_keyboard.rs | 188 ++++++++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 examples/rp/src/bin/usb_hid_keyboard.rs diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 7c5a9dfb..c812cb3e 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -40,6 +40,7 @@ display-interface = "0.4.1" byte-slice-cast = { version = "1.2.0", default-features = false } smart-leds = "0.3.0" heapless = "0.7.15" +usbd-hid = "0.6.1" embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } embedded-hal-async = "0.2.0-alpha.2" diff --git a/examples/rp/src/bin/usb_hid_keyboard.rs b/examples/rp/src/bin/usb_hid_keyboard.rs new file mode 100644 index 00000000..99af1f02 --- /dev/null +++ b/examples/rp/src/bin/usb_hid_keyboard.rs @@ -0,0 +1,188 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use core::sync::atomic::{AtomicBool, Ordering}; + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::join::join; +use embassy_rp::bind_interrupts; +use embassy_rp::gpio::{Input, Pull}; +use embassy_rp::peripherals::USB; +use embassy_rp::usb::{Driver, InterruptHandler}; +use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; +use embassy_usb::control::OutResponse; +use embassy_usb::{Builder, Config, Handler}; +use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + USBCTRL_IRQ => InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + // Create the driver, from the HAL. + let driver = Driver::new(p.USB, Irqs); + + // Create embassy-usb Config + let mut config = Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Embassy"); + config.product = Some("HID keyboard example"); + config.serial_number = Some("12345678"); + config.max_power = 100; + config.max_packet_size_0 = 64; + + // Create embassy-usb DeviceBuilder using the driver and config. + // It needs some buffers for building the descriptors. + let mut device_descriptor = [0; 256]; + let mut config_descriptor = [0; 256]; + let mut bos_descriptor = [0; 256]; + // You can also add a Microsoft OS descriptor. + // let mut msos_descriptor = [0; 256]; + let mut control_buf = [0; 64]; + let request_handler = MyRequestHandler {}; + let mut device_handler = MyDeviceHandler::new(); + + let mut state = State::new(); + + let mut builder = Builder::new( + driver, + config, + &mut device_descriptor, + &mut config_descriptor, + &mut bos_descriptor, + // &mut msos_descriptor, + &mut control_buf, + ); + + builder.handler(&mut device_handler); + + // Create classes on the builder. + let config = embassy_usb::class::hid::Config { + report_descriptor: KeyboardReport::desc(), + request_handler: Some(&request_handler), + poll_ms: 60, + max_packet_size: 64, + }; + let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config); + + // Build the builder. + let mut usb = builder.build(); + + // Run the USB device. + let usb_fut = usb.run(); + + // Set up the signal pin that will be used to trigger the keyboard. + let mut signal_pin = Input::new(p.PIN_16, Pull::None); + + let (reader, mut writer) = hid.split(); + + // Do stuff with the class! + let in_fut = async { + loop { + info!("Waiting for HIGH on pin 16"); + signal_pin.wait_for_high().await; + info!("HIGH DETECTED"); + // Create a report with the A key pressed. (no shift modifier) + let report = KeyboardReport { + keycodes: [4, 0, 0, 0, 0, 0], + leds: 0, + modifier: 0, + reserved: 0, + }; + // Send the report. + match writer.write_serialize(&report).await { + Ok(()) => {} + Err(e) => warn!("Failed to send report: {:?}", e), + }; + signal_pin.wait_for_low().await; + info!("LOW DETECTED"); + let report = KeyboardReport { + keycodes: [0, 0, 0, 0, 0, 0], + leds: 0, + modifier: 0, + reserved: 0, + }; + match writer.write_serialize(&report).await { + Ok(()) => {} + Err(e) => warn!("Failed to send report: {:?}", e), + }; + } + }; + + let out_fut = async { + reader.run(false, &request_handler).await; + }; + + // Run everything concurrently. + // If we had made everything `'static` above instead, we could do this using separate tasks instead. + join(usb_fut, join(in_fut, out_fut)).await; +} + +struct MyRequestHandler {} + +impl RequestHandler for MyRequestHandler { + fn get_report(&self, id: ReportId, _buf: &mut [u8]) -> Option { + info!("Get report for {:?}", id); + None + } + + fn set_report(&self, id: ReportId, data: &[u8]) -> OutResponse { + info!("Set report for {:?}: {=[u8]}", id, data); + OutResponse::Accepted + } + + fn set_idle_ms(&self, id: Option, dur: u32) { + info!("Set idle rate for {:?} to {:?}", id, dur); + } + + fn get_idle_ms(&self, id: Option) -> Option { + info!("Get idle rate for {:?}", id); + None + } +} + +struct MyDeviceHandler { + configured: AtomicBool, +} + +impl MyDeviceHandler { + fn new() -> Self { + MyDeviceHandler { + configured: AtomicBool::new(false), + } + } +} + +impl Handler for MyDeviceHandler { + fn enabled(&mut self, enabled: bool) { + self.configured.store(false, Ordering::Relaxed); + if enabled { + info!("Device enabled"); + } else { + info!("Device disabled"); + } + } + + fn reset(&mut self) { + self.configured.store(false, Ordering::Relaxed); + info!("Bus reset, the Vbus current limit is 100mA"); + } + + fn addressed(&mut self, addr: u8) { + self.configured.store(false, Ordering::Relaxed); + info!("USB address set to: {}", addr); + } + + fn configured(&mut self, configured: bool) { + self.configured.store(configured, Ordering::Relaxed); + if configured { + info!("Device configured, it may now draw up to the configured current limit from Vbus.") + } else { + info!("Device is no longer configured, the Vbus current limit is 100mA."); + } + } +} From 582006c75cdd7e9d819bcacc0f6724c05f161bee Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 16 Jul 2023 09:32:54 -0500 Subject: [PATCH 108/148] wpan/mac: further cleanup --- embassy-stm32-wpan/src/mac/event.rs | 119 ++++++++++++++++++++ embassy-stm32-wpan/src/mac/ioctl.rs | 124 +++++++++++++++++++++ embassy-stm32-wpan/src/mac/mod.rs | 14 +-- embassy-stm32-wpan/src/mac/runner.rs | 161 ++------------------------- 4 files changed, 257 insertions(+), 161 deletions(-) create mode 100644 embassy-stm32-wpan/src/mac/ioctl.rs diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs index dfce21fe..ea326a33 100644 --- a/embassy-stm32-wpan/src/mac/event.rs +++ b/embassy-stm32-wpan/src/mac/event.rs @@ -1,3 +1,8 @@ +use core::cell::RefCell; + +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::pubsub::{PubSubChannel, Subscriber}; + use super::helpers::to_u16; use super::indications::{ AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication, @@ -25,6 +30,7 @@ pub trait ParseableMacEvent { Self: Sized; } +#[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum MacEvent { MlmeAssociateCnf(AssociateConfirm), @@ -92,3 +98,116 @@ impl TryFrom<&[u8]> for MacEvent { } } } + +// TODO this PubSub can probably be replaced with shared memory to make it a bit more efficient. +pub type EventQueue = PubSubChannel; +pub type EventSubscriber<'a> = Subscriber<'a, NoopRawMutex, Message, 2, 1, 1>; + +pub struct Events { + pub queue: EventQueue, + pub mask: SharedEventMask, +} + +impl Events { + pub fn new() -> Self { + Self { + queue: EventQueue::new(), + mask: SharedEventMask::default(), + } + } +} + +#[derive(Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct Status { + pub event_type: MacEvent, + pub status: u32, +} + +#[derive(Clone, Copy)] +pub enum Payload { + None, + // BssInfo(BssInfo), +} + +#[derive(Clone)] + +pub struct Message { + pub header: Status, + pub payload: Payload, +} + +impl Message { + pub fn new(status: Status, payload: Payload) -> Self { + Self { + header: status, + payload, + } + } +} + +#[derive(Default)] +struct EventMask { + mask: [u32; Self::WORD_COUNT], +} + +impl EventMask { + const WORD_COUNT: usize = ((Event::LAST as u32 + (u32::BITS - 1)) / u32::BITS) as usize; + + fn enable(&mut self, event: MacEvent) { + let n = event as u32; + let word = n / u32::BITS; + let bit = n % u32::BITS; + + self.mask[word as usize] |= 1 << bit; + } + + fn disable(&mut self, event: MacEvent) { + let n = event as u32; + let word = n / u32::BITS; + let bit = n % u32::BITS; + + self.mask[word as usize] &= !(1 << bit); + } + + fn is_enabled(&self, event: MacEvent) -> bool { + let n = event as u32; + let word = n / u32::BITS; + let bit = n % u32::BITS; + + self.mask[word as usize] & (1 << bit) > 0 + } +} + +#[derive(Default)] + +pub struct SharedEventMask { + mask: RefCell, +} + +impl SharedEventMask { + pub fn enable(&self, events: &[MacEvent]) { + let mut mask = self.mask.borrow_mut(); + for event in events { + mask.enable(*event); + } + } + + #[allow(dead_code)] + pub fn disable(&self, events: &[MacEvent]) { + let mut mask = self.mask.borrow_mut(); + for event in events { + mask.disable(*event); + } + } + + pub fn disable_all(&self) { + let mut mask = self.mask.borrow_mut(); + mask.mask = Default::default(); + } + + pub fn is_enabled(&self, event: MacEvent) -> bool { + let mask = self.mask.borrow(); + mask.is_enabled(event) + } +} diff --git a/embassy-stm32-wpan/src/mac/ioctl.rs b/embassy-stm32-wpan/src/mac/ioctl.rs new file mode 100644 index 00000000..0fe55cd6 --- /dev/null +++ b/embassy-stm32-wpan/src/mac/ioctl.rs @@ -0,0 +1,124 @@ +use core::cell::{Cell, RefCell}; +use core::future::poll_fn; +use core::task::{Poll, Waker}; + +use embassy_sync::waitqueue::WakerRegistration; + +#[derive(Clone, Copy)] +pub enum IoctlType { + Get = 0, + Set = 2, +} + +#[derive(Clone, Copy)] +pub struct PendingIoctl { + pub buf: *mut [u8], + pub kind: IoctlType, + pub cmd: u32, + pub iface: u32, +} + +#[derive(Clone, Copy)] +enum IoctlStateInner { + Pending(PendingIoctl), + Sent { buf: *mut [u8] }, + Done { resp_len: usize }, +} + +struct Wakers { + control: WakerRegistration, + runner: WakerRegistration, +} + +impl Default for Wakers { + fn default() -> Self { + Self { + control: WakerRegistration::new(), + runner: WakerRegistration::new(), + } + } +} + +pub struct IoctlState { + state: Cell, + wakers: RefCell, +} + +impl IoctlState { + pub fn new() -> Self { + Self { + state: Cell::new(IoctlStateInner::Done { resp_len: 0 }), + wakers: Default::default(), + } + } + + fn wake_control(&self) { + self.wakers.borrow_mut().control.wake(); + } + + fn register_control(&self, waker: &Waker) { + self.wakers.borrow_mut().control.register(waker); + } + + fn wake_runner(&self) { + self.wakers.borrow_mut().runner.wake(); + } + + fn register_runner(&self, waker: &Waker) { + self.wakers.borrow_mut().runner.register(waker); + } + + pub async fn wait_complete(&self) -> usize { + poll_fn(|cx| { + if let IoctlStateInner::Done { resp_len } = self.state.get() { + Poll::Ready(resp_len) + } else { + self.register_control(cx.waker()); + Poll::Pending + } + }) + .await + } + + pub async fn wait_pending(&self) -> PendingIoctl { + let pending = poll_fn(|cx| { + if let IoctlStateInner::Pending(pending) = self.state.get() { + Poll::Ready(pending) + } else { + self.register_runner(cx.waker()); + Poll::Pending + } + }) + .await; + + self.state.set(IoctlStateInner::Sent { buf: pending.buf }); + pending + } + + pub fn cancel_ioctl(&self) { + self.state.set(IoctlStateInner::Done { resp_len: 0 }); + } + + pub async fn do_ioctl(&self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize { + self.state + .set(IoctlStateInner::Pending(PendingIoctl { buf, kind, cmd, iface })); + self.wake_runner(); + self.wait_complete().await + } + + pub fn ioctl_done(&self, response: &[u8]) { + if let IoctlStateInner::Sent { buf } = self.state.get() { + // trace!("IOCTL Response: {:02x}", Bytes(response)); + + // TODO fix this + (unsafe { &mut *buf }[..response.len()]).copy_from_slice(response); + + self.state.set(IoctlStateInner::Done { + resp_len: response.len(), + }); + self.wake_control(); + } else { + warn!("IOCTL Response but no pending Ioctl"); + } + } +} diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs index e27f0ba7..67dc429e 100644 --- a/embassy-stm32-wpan/src/mac/mod.rs +++ b/embassy-stm32-wpan/src/mac/mod.rs @@ -4,6 +4,7 @@ pub mod control; pub mod event; mod helpers; pub mod indications; +mod ioctl; mod macros; mod opcodes; pub mod responses; @@ -14,11 +15,10 @@ use core::slice; use embassy_net_driver_channel as ch; -use crate::bus::Bus; -pub use crate::bus::SpiBusCyw43; pub use crate::mac::control::{Control, Error as ControlError}; -pub use crate::runner::Runner; -pub use crate::structs::BssInfo; +use crate::mac::event::Events; +use crate::mac::ioctl::IoctlState; +pub use crate::mac::runner::Runner; use crate::sub::mac::Mac; const MTU: usize = 1514; @@ -76,15 +76,15 @@ impl PowerManagementMode { pub type NetDriver<'a> = ch::Device<'a, MTU>; -pub async fn new<'a, PWR, SPI>( +pub async fn new<'a>( state: &'a mut State, mac_subsystem: Mac, firmware: &[u8], -) -> (NetDriver<'a>, Control<'a>, Runner<'a, PWR, SPI>) { +) -> (NetDriver<'a>, Control<'a>, Runner<'a>) { let (ch_runner, device) = ch::new(&mut state.ch, [0; 6]); let state_ch = ch_runner.state_runner(); - let mut runner = Runner::new(ch_runner, Bus::new(pwr, spi), &state.ioctl_state, &state.events); + let mut runner = Runner::new(ch_runner, mac_subsystem, &state.ioctl_state, &state.events); runner.init(firmware).await; diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index 7f0bbd67..fbb7cb74 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -2,29 +2,12 @@ use embassy_futures::select::{select3, Either3}; use embassy_net_driver_channel as ch; use embassy_sync::pubsub::PubSubBehavior; +use crate::mac::event::Events; +use crate::mac::ioctl::{IoctlState, PendingIoctl}; +use crate::mac::MTU; use crate::sub::mac::Mac; -#[cfg(feature = "firmware-logs")] -struct LogState { - addr: u32, - last_idx: usize, - buf: [u8; 256], - buf_count: usize, -} - -#[cfg(feature = "firmware-logs")] -impl Default for LogState { - fn default() -> Self { - Self { - addr: Default::default(), - last_idx: Default::default(), - buf: [0; 256], - buf_count: Default::default(), - } - } -} - -pub struct Runner<'a, PWR, SPI> { +pub struct Runner<'a> { ch: ch::Runner<'a, MTU>, mac: Mac, @@ -34,32 +17,18 @@ pub struct Runner<'a, PWR, SPI> { sdpcm_seq_max: u8, events: &'a Events, - - #[cfg(feature = "firmware-logs")] - log: LogState, } -impl<'a, PWR, SPI> Runner<'a, PWR, SPI> -where - PWR: OutputPin, - SPI: SpiBusCyw43, -{ - pub(crate) fn new( - ch: ch::Runner<'a, MTU>, - bus: Bus, - ioctl_state: &'a IoctlState, - events: &'a Events, - ) -> Self { +impl<'a> Runner<'a> { + pub(crate) fn new(ch: ch::Runner<'a, MTU>, mac: Mac, ioctl_state: &'a IoctlState, events: &'a Events) -> Self { Self { ch, - bus, + mac, ioctl_state, ioctl_id: 0, sdpcm_seq: 0, sdpcm_seq_max: 1, events, - #[cfg(feature = "firmware-logs")] - log: LogState::default(), } } @@ -72,60 +41,6 @@ where debug!("wifi init done"); } - #[cfg(feature = "firmware-logs")] - async fn log_init(&mut self) { - // Initialize shared memory for logging. - - let addr = CHIP.atcm_ram_base_address + CHIP.chip_ram_size - 4 - CHIP.socram_srmem_size; - let shared_addr = self.bus.bp_read32(addr).await; - debug!("shared_addr {:08x}", shared_addr); - - let mut shared = [0; SharedMemData::SIZE]; - self.bus.bp_read(shared_addr, &mut shared).await; - let shared = SharedMemData::from_bytes(&shared); - - self.log.addr = shared.console_addr + 8; - } - - #[cfg(feature = "firmware-logs")] - async fn log_read(&mut self) { - // Read log struct - let mut log = [0; SharedMemLog::SIZE]; - self.bus.bp_read(self.log.addr, &mut log).await; - let log = SharedMemLog::from_bytes(&log); - - let idx = log.idx as usize; - - // If pointer hasn't moved, no need to do anything. - if idx == self.log.last_idx { - return; - } - - // Read entire buf for now. We could read only what we need, but then we - // run into annoying alignment issues in `bp_read`. - let mut buf = [0; 0x400]; - self.bus.bp_read(log.buf, &mut buf).await; - - while self.log.last_idx != idx as usize { - let b = buf[self.log.last_idx]; - if b == b'\r' || b == b'\n' { - if self.log.buf_count != 0 { - let s = unsafe { core::str::from_utf8_unchecked(&self.log.buf[..self.log.buf_count]) }; - debug!("LOGS: {}", s); - self.log.buf_count = 0; - } - } else if self.log.buf_count < self.log.buf.len() { - self.log.buf[self.log.buf_count] = b; - self.log.buf_count += 1; - } - - self.log.last_idx += 1; - if self.log.last_idx == 0x400 { - self.log.last_idx = 0; - } - } - } - pub async fn run(mut self) -> ! { let mut buf = [0; 512]; loop { @@ -424,66 +339,4 @@ where self.bus.wlan_write(&buf[..total_len / 4]).await; } - - async fn core_disable(&mut self, core: Core) { - let base = core.base_addr(); - - // Dummy read? - let _ = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; - - // Check it isn't already reset - let r = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; - if r & AI_RESETCTRL_BIT_RESET != 0 { - return; - } - - self.bus.bp_write8(base + AI_IOCTRL_OFFSET, 0).await; - let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; - - block_for(Duration::from_millis(1)); - - self.bus - .bp_write8(base + AI_RESETCTRL_OFFSET, AI_RESETCTRL_BIT_RESET) - .await; - let _ = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; - } - - async fn core_reset(&mut self, core: Core) { - self.core_disable(core).await; - - let base = core.base_addr(); - self.bus - .bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN) - .await; - let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; - - self.bus.bp_write8(base + AI_RESETCTRL_OFFSET, 0).await; - - Timer::after(Duration::from_millis(1)).await; - - self.bus - .bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_CLOCK_EN) - .await; - let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; - - Timer::after(Duration::from_millis(1)).await; - } - - async fn core_is_up(&mut self, core: Core) -> bool { - let base = core.base_addr(); - - let io = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; - if io & (AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN) != AI_IOCTRL_BIT_CLOCK_EN { - debug!("core_is_up: returning false due to bad ioctrl {:02x}", io); - return false; - } - - let r = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; - if r & (AI_RESETCTRL_BIT_RESET) != 0 { - debug!("core_is_up: returning false due to bad resetctrl {:02x}", r); - return false; - } - - true - } } From e95a7dc555f367534d3b8bc7a9b6f2d361b0d951 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 16 Jul 2023 12:41:57 -0500 Subject: [PATCH 109/148] wpan/mac: use slice view to avoid copy --- embassy-stm32-wpan/src/mac/commands.rs | 83 ++++++++++++++------------ embassy-stm32-wpan/src/mac/typedefs.rs | 2 + embassy-stm32-wpan/src/sub/mac.rs | 9 +-- examples/stm32wb/src/bin/mac_ffd.rs | 5 +- examples/stm32wb/src/bin/mac_rfd.rs | 35 ++++++----- tests/stm32/src/bin/wpan_mac.rs | 6 +- 6 files changed, 77 insertions(+), 63 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/commands.rs b/embassy-stm32-wpan/src/mac/commands.rs index 8cfa0a05..8acae24b 100644 --- a/embassy-stm32-wpan/src/mac/commands.rs +++ b/embassy-stm32-wpan/src/mac/commands.rs @@ -1,15 +1,16 @@ +use core::{mem, slice}; + use super::opcodes::OpcodeM4ToM0; use super::typedefs::{ AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, MacStatus, PanId, PibId, ScanType, SecurityLevel, }; -pub trait MacCommand { +pub trait MacCommand: Sized { const OPCODE: OpcodeM4ToM0; - const SIZE: usize; - fn copy_into_slice(&self, buf: &mut [u8]) { - unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, Self::SIZE) }; + fn payload<'a>(&'a self) -> &'a [u8] { + unsafe { slice::from_raw_parts(self as *const _ as *const u8, mem::size_of::()) } } } @@ -41,7 +42,6 @@ pub struct AssociateRequest { impl MacCommand for AssociateRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateReq; - const SIZE: usize = 25; } /// MLME DISASSOCIATE Request sed to request a disassociation @@ -70,20 +70,22 @@ pub struct DisassociateRequest { impl MacCommand for DisassociateRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDisassociateReq; - const SIZE: usize = 24; } /// MLME GET Request used to request a PIB value #[repr(C)] +#[derive(Default)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GetRequest { /// the name of the PIB attribute to read pub pib_attribute: PibId, + + /// byte stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 3], } impl MacCommand for GetRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq; - const SIZE: usize = 4; } /// MLME GTS Request used to request and maintain GTSs @@ -104,19 +106,20 @@ pub struct GtsRequest { impl MacCommand for GtsRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq; - const SIZE: usize = 12; } #[repr(C)] +#[derive(Default)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ResetRequest { /// MAC PIB attributes are set to their default values or not during reset pub set_default_pib: bool, + /// byte stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 3], } impl MacCommand for ResetRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeResetReq; - const SIZE: usize = 4; } /// MLME RX ENABLE Request used to request that the receiver is either enabled @@ -129,6 +132,8 @@ pub struct RxEnableRequest { /// configure the transceiver to RX with ranging for a value of /// RANGING_ON or to not enable ranging for RANGING_OFF pub ranging_rx_control: u8, + /// byte stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 2], /// number of symbols measured before the receiver is to be enabled or disabled pub rx_on_time: [u8; 4], /// number of symbols for which the receiver is to be enabled @@ -137,19 +142,6 @@ pub struct RxEnableRequest { impl MacCommand for RxEnableRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeRxEnableReq; - const SIZE: usize = 12; - - fn copy_into_slice(&self, buf: &mut [u8]) { - buf[0] = self.defer_permit as u8; - buf[1] = self.ranging_rx_control as u8; - - // stuffing to keep 32bit alignment - buf[2] = 0; - buf[3] = 0; - - buf[4..8].copy_from_slice(&self.rx_on_time); - buf[8..12].copy_from_slice(&self.rx_on_duration); - } } /// MLME SCAN Request used to initiate a channel scan over a given list of channels @@ -172,11 +164,12 @@ pub struct ScanRequest { pub key_id_mode: KeyIdMode, /// index of the key to be used pub key_index: u8, + /// byte stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 2], } impl MacCommand for ScanRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeScanReq; - const SIZE: usize = 20; } /// MLME SET Request used to attempt to write the given value to the indicated PIB attribute @@ -191,13 +184,12 @@ pub struct SetRequest { impl MacCommand for SetRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSetReq; - const SIZE: usize = 8; } /// MLME START Request used by the FFDs to intiate a new PAN or to begin using a new superframe /// configuration -#[derive(Default)] #[repr(C)] +#[derive(Default)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct StartRequest { /// PAN indentifier to used by the device @@ -236,7 +228,6 @@ pub struct StartRequest { impl MacCommand for StartRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeStartReq; - const SIZE: usize = 35; } /// MLME SYNC Request used to synchronize with the coordinator by acquiring and, if @@ -253,11 +244,12 @@ pub struct SyncRequest { /// /// `false` if the MLME is to synchronize with only the next beacon pub track_beacon: bool, + /// byte stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 1], } impl MacCommand for SyncRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSyncReq; - const SIZE: usize = 4; } /// MLME POLL Request propmts the device to request data from the coordinator @@ -278,11 +270,12 @@ pub struct PollRequest { pub key_source: [u8; 8], /// PAN identifier of the coordinator pub coord_pan_id: PanId, + /// byte stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 2], } impl MacCommand for PollRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmePollReq; - const SIZE: usize = 24; } /// MLME DPS Request allows the next higher layer to request that the PHY utilize a @@ -297,33 +290,38 @@ pub struct DpsRequest { /// the number of symbols for which the transmitter and receiver will utilize the /// respective DPS indices dps_index_duration: u8, + /// byte stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 1], } impl MacCommand for DpsRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDpsReq; - const SIZE: usize = 4; } /// MLME SOUNDING request primitive which is used by the next higher layer to request that /// the PHY respond with channel sounding information #[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct SoundingRequest; +pub struct SoundingRequest { + /// byte stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 4], +} impl MacCommand for SoundingRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSoundingReq; - const SIZE: usize = 4; } /// MLME CALIBRATE request primitive which used to obtain the results of a ranging /// calibration request from an RDEV #[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct CalibrateRequest; +pub struct CalibrateRequest { + /// byte stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 4], +} impl MacCommand for CalibrateRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeCalibrateReq; - const SIZE: usize = 4; } /// MCPS DATA Request used for MAC data related requests from the application @@ -370,6 +368,15 @@ pub struct DataRequest { pub datrate: u8, } +impl DataRequest { + pub fn set_buffer<'a>(&'a mut self, buf: &'a [u8]) -> &mut Self { + self.msdu_ptr = &buf as *const _ as *const u8; + self.msdu_length = buf.len() as u8; + + self + } +} + impl Default for DataRequest { fn default() -> Self { Self { @@ -397,7 +404,6 @@ impl Default for DataRequest { impl MacCommand for DataRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsDataReq; - const SIZE: usize = 40; } /// for MCPS PURGE Request used to purge an MSDU from the transaction queue @@ -407,11 +413,12 @@ pub struct PurgeRequest { /// the handle associated with the MSDU to be purged from the transaction /// queue pub msdu_handle: u8, + /// byte stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 3], } impl MacCommand for PurgeRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsPurgeReq; - const SIZE: usize = 4; } /// MLME ASSOCIATE Response used to initiate a response to an MLME-ASSOCIATE.indication @@ -434,11 +441,12 @@ pub struct AssociateResponse { pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, + /// byte stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 2], } impl MacCommand for AssociateResponse { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateRes; - const SIZE: usize = 24; } /// MLME ORPHAN Response used to respond to the MLME ORPHAN Indication @@ -459,9 +467,10 @@ pub struct OrphanResponse { pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, + /// byte stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 2], } impl MacCommand for OrphanResponse { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeOrphanRes; - const SIZE: usize = 24; } diff --git a/embassy-stm32-wpan/src/mac/typedefs.rs b/embassy-stm32-wpan/src/mac/typedefs.rs index 30c7731b..98c67c86 100644 --- a/embassy-stm32-wpan/src/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/mac/typedefs.rs @@ -37,9 +37,11 @@ numeric_enum! { numeric_enum! { #[repr(u8)] /// this enum contains all the MAC PIB Ids + #[derive(Default)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum PibId { // PHY + #[default] CurrentChannel = 0x00, ChannelsSupported = 0x01, TransmitPower = 0x02, diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs index 4893cb47..d30ed2f1 100644 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ b/embassy-stm32-wpan/src/sub/mac.rs @@ -85,12 +85,7 @@ impl Mac { where T: MacCommand, { - let mut payload = [0u8; MAX_PACKET_SIZE]; - cmd.copy_into_slice(&mut payload); - - let response = self - .tl_write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]) - .await; + let response = self.tl_write_and_get_response(T::OPCODE as u16, cmd.payload()).await; if response == 0x00 { Ok(()) @@ -107,8 +102,6 @@ impl Mac { } } -const MAX_PACKET_SIZE: usize = 255; - impl evt::MemoryManager for Mac { /// SAFETY: passing a pointer to something other than a managed event packet is UB unsafe fn drop_event_packet(_: *mut EvtPacket) { diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index e4d81997..f8c8ba28 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -67,7 +67,10 @@ async fn main(spawner: Spawner) { info!("resetting"); mbox.mac_subsystem - .send_command(&ResetRequest { set_default_pib: true }) + .send_command(&ResetRequest { + set_default_pib: true, + ..Default::default() + }) .await .unwrap(); let evt = mbox.mac_subsystem.read().await; diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index b2dac72c..b0eb9106 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -69,7 +69,10 @@ async fn main(spawner: Spawner) { info!("resetting"); mbox.mac_subsystem - .send_command(&ResetRequest { set_default_pib: true }) + .send_command(&ResetRequest { + set_default_pib: true, + ..Default::default() + }) .await .unwrap(); let evt = mbox.mac_subsystem.read().await; @@ -91,6 +94,7 @@ async fn main(spawner: Spawner) { mbox.mac_subsystem .send_command(&GetRequest { pib_attribute: PibId::ExtendedAddress, + ..Default::default() }) .await .unwrap(); @@ -141,23 +145,22 @@ async fn main(spawner: Spawner) { info!("{:#x}", evt); info!("sending data"); - let mut data_buffer = [0u8; 256]; let data = b"Hello from embassy!"; - data_buffer[..data.len()].copy_from_slice(data); mbox.mac_subsystem - .send_command(&DataRequest { - src_addr_mode: AddressMode::Short, - dst_addr_mode: AddressMode::Short, - dst_pan_id: PanId([0x1A, 0xAA]), - dst_address: MacAddress::BROADCAST, - msdu_handle: 0x02, - ack_tx: 0x00, - gts_tx: false, - msdu_ptr: &data_buffer as *const _ as *const u8, - msdu_length: data.len() as u8, - security_level: SecurityLevel::Unsecure, - ..Default::default() - }) + .send_command( + DataRequest { + src_addr_mode: AddressMode::Short, + dst_addr_mode: AddressMode::Short, + dst_pan_id: PanId([0x1A, 0xAA]), + dst_address: MacAddress::BROADCAST, + msdu_handle: 0x02, + ack_tx: 0x00, + gts_tx: false, + security_level: SecurityLevel::Unsecure, + ..Default::default() + } + .set_buffer(data), + ) .await .unwrap(); let evt = mbox.mac_subsystem.read().await; diff --git a/tests/stm32/src/bin/wpan_mac.rs b/tests/stm32/src/bin/wpan_mac.rs index cfa0aca3..2fc15dc9 100644 --- a/tests/stm32/src/bin/wpan_mac.rs +++ b/tests/stm32/src/bin/wpan_mac.rs @@ -49,7 +49,10 @@ async fn main(spawner: Spawner) { info!("resetting"); mbox.mac_subsystem - .send_command(&ResetRequest { set_default_pib: true }) + .send_command(&ResetRequest { + set_default_pib: true, + ..Default::default() + }) .await .unwrap(); let evt = mbox.mac_subsystem.read().await; @@ -71,6 +74,7 @@ async fn main(spawner: Spawner) { mbox.mac_subsystem .send_command(&GetRequest { pib_attribute: PibId::ExtendedAddress, + ..Default::default() }) .await .unwrap(); From 7c465465c1a97234c3fbeb18154bfd7f79ab07f2 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 16 Jul 2023 13:59:15 -0500 Subject: [PATCH 110/148] wpan: use builtin conversion methods --- embassy-stm32-wpan/src/mac/event.rs | 4 ++-- embassy-stm32-wpan/src/mac/helpers.rs | 7 ------- embassy-stm32-wpan/src/mac/indications.rs | 13 ++++++------- embassy-stm32-wpan/src/mac/mod.rs | 1 - embassy-stm32-wpan/src/mac/responses.rs | 15 +++++++-------- 5 files changed, 15 insertions(+), 25 deletions(-) delete mode 100644 embassy-stm32-wpan/src/mac/helpers.rs diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs index dfce21fe..c2bdc7e1 100644 --- a/embassy-stm32-wpan/src/mac/event.rs +++ b/embassy-stm32-wpan/src/mac/event.rs @@ -1,4 +1,3 @@ -use super::helpers::to_u16; use super::indications::{ AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication, DpsIndication, GtsIndication, OrphanIndication, PollIndication, SyncLossIndication, @@ -58,7 +57,8 @@ impl TryFrom<&[u8]> for MacEvent { type Error = (); fn try_from(value: &[u8]) -> Result { - let opcode = to_u16(&value[0..2]); + let opcode = u16::from_le_bytes(value[0..2].try_into().unwrap()); + let opcode = OpcodeM0ToM4::try_from(opcode)?; let buf = &value[2..]; diff --git a/embassy-stm32-wpan/src/mac/helpers.rs b/embassy-stm32-wpan/src/mac/helpers.rs deleted file mode 100644 index 5a5bf8a8..00000000 --- a/embassy-stm32-wpan/src/mac/helpers.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub fn to_u16(buf: &[u8]) -> u16 { - ((buf[1] as u16) << 8) | buf[0] as u16 -} - -pub fn to_u32(buf: &[u8]) -> u32 { - ((buf[0] as u32) << 0) + ((buf[1] as u32) << 8) + ((buf[2] as u32) << 16) + ((buf[3] as u32) << 24) -} diff --git a/embassy-stm32-wpan/src/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs index 6df4aa23..436b9ac9 100644 --- a/embassy-stm32-wpan/src/mac/indications.rs +++ b/embassy-stm32-wpan/src/mac/indications.rs @@ -1,6 +1,5 @@ use super::consts::MAX_PENDING_ADDRESS; use super::event::ParseableMacEvent; -use super::helpers::to_u32; use super::typedefs::{ AddressMode, Capabilities, DisassociationReason, KeyIdMode, MacAddress, MacChannel, MacStatus, PanDescriptor, PanId, SecurityLevel, @@ -114,7 +113,7 @@ impl ParseableMacEvent for BeaconNotifyIndication { ]; Ok(Self { - sdu_ptr: to_u32(&buf[0..4]) as *const u8, + sdu_ptr: u32::from_le_bytes(buf[0..4].try_into().unwrap()) as *const u8, pan_descriptor: PanDescriptor::try_from(&buf[4..26])?, addr_list, bsn: buf[82], @@ -405,7 +404,7 @@ impl ParseableMacEvent for DataIndication { }; Ok(Self { - msdu_ptr: to_u32(&buf[0..4]) as *const u8, + msdu_ptr: u32::from_le_bytes(buf[0..4].try_into().unwrap()) as *const u8, src_addr_mode, src_pan_id: PanId([buf[5], buf[6]]), src_address, @@ -424,10 +423,10 @@ impl ParseableMacEvent for DataIndication { uwn_preamble_symbol_repetitions: buf[45], datrate: buf[46], ranging_received: buf[47], - ranging_counter_start: to_u32(&buf[48..52]), - ranging_counter_stop: to_u32(&buf[52..56]), - ranging_tracking_interval: to_u32(&buf[56..60]), - ranging_offset: to_u32(&buf[60..64]), + ranging_counter_start: u32::from_le_bytes(buf[48..52].try_into().unwrap()), + ranging_counter_stop: u32::from_le_bytes(buf[52..56].try_into().unwrap()), + ranging_tracking_interval: u32::from_le_bytes(buf[56..60].try_into().unwrap()), + ranging_offset: u32::from_le_bytes(buf[60..64].try_into().unwrap()), ranging_fom: buf[65], rssi: buf[66], }) diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs index 1af8fe6b..8d5edad6 100644 --- a/embassy-stm32-wpan/src/mac/mod.rs +++ b/embassy-stm32-wpan/src/mac/mod.rs @@ -1,7 +1,6 @@ pub mod commands; mod consts; pub mod event; -mod helpers; pub mod indications; mod macros; mod opcodes; diff --git a/embassy-stm32-wpan/src/mac/responses.rs b/embassy-stm32-wpan/src/mac/responses.rs index 2f6f5bf5..d29257f8 100644 --- a/embassy-stm32-wpan/src/mac/responses.rs +++ b/embassy-stm32-wpan/src/mac/responses.rs @@ -1,6 +1,5 @@ use super::consts::{MAX_ED_SCAN_RESULTS_SUPPORTED, MAX_PAN_DESC_SUPPORTED, MAX_SOUNDING_LIST_SUPPORTED}; use super::event::ParseableMacEvent; -use super::helpers::to_u32; use super::typedefs::{ AddressMode, AssociationStatus, KeyIdMode, MacAddress, MacStatus, PanDescriptor, PanId, PibId, ScanType, SecurityLevel, @@ -100,7 +99,7 @@ impl ParseableMacEvent for GetConfirm { fn try_parse(buf: &[u8]) -> Result { Self::validate(buf)?; - let address = to_u32(&buf[0..4]); + let address = u32::from_le_bytes(buf[0..4].try_into().unwrap()); Ok(Self { pib_attribute_value_ptr: address as *const u8, @@ -357,8 +356,8 @@ impl ParseableMacEvent for CalibrateConfirm { Ok(Self { status: MacStatus::try_from(buf[0])?, // 3 byte stuffing - cal_tx_rmaker_offset: to_u32(&buf[4..8]), - cal_rx_rmaker_offset: to_u32(&buf[8..12]), + cal_tx_rmaker_offset: u32::from_le_bytes(buf[4..8].try_into().unwrap()), + cal_rx_rmaker_offset: u32::from_le_bytes(buf[8..12].try_into().unwrap()), }) } } @@ -400,10 +399,10 @@ impl ParseableMacEvent for DataConfirm { time_stamp: [buf[1], buf[2], buf[3], buf[4]], ranging_received: buf[5], status: MacStatus::try_from(buf[6])?, - ranging_counter_start: to_u32(&buf[7..11]), - ranging_counter_stop: to_u32(&buf[11..15]), - ranging_tracking_interval: to_u32(&buf[15..19]), - ranging_offset: to_u32(&buf[19..23]), + ranging_counter_start: u32::from_le_bytes(buf[7..11].try_into().unwrap()), + ranging_counter_stop: u32::from_le_bytes(buf[11..15].try_into().unwrap()), + ranging_tracking_interval: u32::from_le_bytes(buf[15..19].try_into().unwrap()), + ranging_offset: u32::from_le_bytes(buf[19..23].try_into().unwrap()), ranging_fom: buf[24], }) } From 28b419d65ede6ff29c79dbcaa27145f1c3458a57 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 16 Jul 2023 15:09:30 -0500 Subject: [PATCH 111/148] wpan/mac: use lifetimes to control events --- embassy-stm32-wpan/src/mac/event.rs | 169 ++++++++------ embassy-stm32-wpan/src/mac/indications.rs | 269 ++------------------- embassy-stm32-wpan/src/mac/responses.rs | 271 ++++------------------ embassy-stm32-wpan/src/sub/mac.rs | 9 +- examples/stm32wb/src/bin/mac_ffd.rs | 46 ++-- examples/stm32wb/src/bin/mac_rfd.rs | 55 +++-- tests/stm32/src/bin/wpan_mac.rs | 32 ++- 7 files changed, 243 insertions(+), 608 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs index c2bdc7e1..67f207d5 100644 --- a/embassy-stm32-wpan/src/mac/event.rs +++ b/embassy-stm32-wpan/src/mac/event.rs @@ -1,3 +1,5 @@ +use core::mem; + use super::indications::{ AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication, DpsIndication, GtsIndication, OrphanIndication, PollIndication, SyncLossIndication, @@ -6,89 +8,110 @@ use super::responses::{ AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm, PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm, }; +use crate::evt::EvtBox; use crate::mac::opcodes::OpcodeM0ToM4; +use crate::sub::mac::Mac; -pub trait ParseableMacEvent { - const SIZE: usize; - - fn validate(buf: &[u8]) -> Result<(), ()> { - if buf.len() < Self::SIZE { - return Err(()); +pub(crate) trait ParseableMacEvent: Sized { + fn from_buffer<'a>(buf: &'a [u8]) -> Result<&'a Self, ()> { + if buf.len() < mem::size_of::() { + Err(()) + } else { + Ok(unsafe { &*(buf as *const _ as *const Self) }) } + } +} - Ok(()) +pub struct Event { + event_box: EvtBox, +} + +impl Event { + pub(crate) fn new(event_box: EvtBox) -> Self { + Self { event_box } } - fn try_parse(buf: &[u8]) -> Result - where - Self: Sized; -} - -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum MacEvent { - MlmeAssociateCnf(AssociateConfirm), - MlmeDisassociateCnf(DisassociateConfirm), - MlmeGetCnf(GetConfirm), - MlmeGtsCnf(GtsConfirm), - MlmeResetCnf(ResetConfirm), - MlmeRxEnableCnf(RxEnableConfirm), - MlmeScanCnf(ScanConfirm), - MlmeSetCnf(SetConfirm), - MlmeStartCnf(StartConfirm), - MlmePollCnf(PollConfirm), - MlmeDpsCnf(DpsConfirm), - MlmeSoundingCnf(SoundingConfirm), - MlmeCalibrateCnf(CalibrateConfirm), - McpsDataCnf(DataConfirm), - McpsPurgeCnf(PurgeConfirm), - MlmeAssociateInd(AssociateIndication), - MlmeDisassociateInd(DisassociateIndication), - MlmeBeaconNotifyInd(BeaconNotifyIndication), - MlmeCommStatusInd(CommStatusIndication), - MlmeGtsInd(GtsIndication), - MlmeOrphanInd(OrphanIndication), - MlmeSyncLossInd(SyncLossIndication), - MlmeDpsInd(DpsIndication), - McpsDataInd(DataIndication), - MlmePollInd(PollIndication), -} - -impl TryFrom<&[u8]> for MacEvent { - type Error = (); - - fn try_from(value: &[u8]) -> Result { - let opcode = u16::from_le_bytes(value[0..2].try_into().unwrap()); + pub fn mac_event<'a>(&'a self) -> Result, ()> { + let payload = self.event_box.payload(); + let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap()); let opcode = OpcodeM0ToM4::try_from(opcode)?; - let buf = &value[2..]; - match opcode { - OpcodeM0ToM4::MlmeAssociateCnf => Ok(Self::MlmeAssociateCnf(AssociateConfirm::try_parse(buf)?)), - OpcodeM0ToM4::MlmeDisassociateCnf => Ok(Self::MlmeDisassociateCnf(DisassociateConfirm::try_parse(buf)?)), - OpcodeM0ToM4::MlmeGetCnf => Ok(Self::MlmeGetCnf(GetConfirm::try_parse(buf)?)), - OpcodeM0ToM4::MlmeGtsCnf => Ok(Self::MlmeGtsCnf(GtsConfirm::try_parse(buf)?)), - OpcodeM0ToM4::MlmeResetCnf => Ok(Self::MlmeResetCnf(ResetConfirm::try_parse(buf)?)), - OpcodeM0ToM4::MlmeRxEnableCnf => Ok(Self::MlmeRxEnableCnf(RxEnableConfirm::try_parse(buf)?)), - OpcodeM0ToM4::MlmeScanCnf => Ok(Self::MlmeScanCnf(ScanConfirm::try_parse(buf)?)), - OpcodeM0ToM4::MlmeSetCnf => Ok(Self::MlmeSetCnf(SetConfirm::try_parse(buf)?)), - OpcodeM0ToM4::MlmeStartCnf => Ok(Self::MlmeStartCnf(StartConfirm::try_parse(buf)?)), - OpcodeM0ToM4::MlmePollCnf => Ok(Self::MlmePollCnf(PollConfirm::try_parse(buf)?)), - OpcodeM0ToM4::MlmeDpsCnf => Ok(Self::MlmeDpsCnf(DpsConfirm::try_parse(buf)?)), - OpcodeM0ToM4::MlmeSoundingCnf => Ok(Self::MlmeSoundingCnf(SoundingConfirm::try_parse(buf)?)), - OpcodeM0ToM4::MlmeCalibrateCnf => Ok(Self::MlmeCalibrateCnf(CalibrateConfirm::try_parse(buf)?)), - OpcodeM0ToM4::McpsDataCnf => Ok(Self::McpsDataCnf(DataConfirm::try_parse(buf)?)), - OpcodeM0ToM4::McpsPurgeCnf => Ok(Self::McpsPurgeCnf(PurgeConfirm::try_parse(buf)?)), - OpcodeM0ToM4::MlmeAssociateInd => Ok(Self::MlmeAssociateInd(AssociateIndication::try_parse(buf)?)), - OpcodeM0ToM4::MlmeDisassociateInd => Ok(Self::MlmeDisassociateInd(DisassociateIndication::try_parse(buf)?)), - OpcodeM0ToM4::MlmeBeaconNotifyInd => Ok(Self::MlmeBeaconNotifyInd(BeaconNotifyIndication::try_parse(buf)?)), - OpcodeM0ToM4::MlmeCommStatusInd => Ok(Self::MlmeCommStatusInd(CommStatusIndication::try_parse(buf)?)), - OpcodeM0ToM4::MlmeGtsInd => Ok(Self::MlmeGtsInd(GtsIndication::try_parse(buf)?)), - OpcodeM0ToM4::MlmeOrphanInd => Ok(Self::MlmeOrphanInd(OrphanIndication::try_parse(buf)?)), - OpcodeM0ToM4::MlmeSyncLossInd => Ok(Self::MlmeSyncLossInd(SyncLossIndication::try_parse(buf)?)), - OpcodeM0ToM4::MlmeDpsInd => Ok(Self::MlmeDpsInd(DpsIndication::try_parse(buf)?)), - OpcodeM0ToM4::McpsDataInd => Ok(Self::McpsDataInd(DataIndication::try_parse(buf)?)), - OpcodeM0ToM4::MlmePollInd => Ok(Self::MlmePollInd(PollIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeAssociateCnf => Ok(MacEvent::MlmeAssociateCnf(AssociateConfirm::from_buffer( + &payload[2..], + )?)), + OpcodeM0ToM4::MlmeDisassociateCnf => Ok(MacEvent::MlmeDisassociateCnf(DisassociateConfirm::from_buffer( + &payload[2..], + )?)), + OpcodeM0ToM4::MlmeGetCnf => Ok(MacEvent::MlmeGetCnf(GetConfirm::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::MlmeGtsCnf => Ok(MacEvent::MlmeGtsCnf(GtsConfirm::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::MlmeResetCnf => Ok(MacEvent::MlmeResetCnf(ResetConfirm::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::MlmeRxEnableCnf => { + Ok(MacEvent::MlmeRxEnableCnf(RxEnableConfirm::from_buffer(&payload[2..])?)) + } + OpcodeM0ToM4::MlmeScanCnf => Ok(MacEvent::MlmeScanCnf(ScanConfirm::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::MlmeSetCnf => Ok(MacEvent::MlmeSetCnf(SetConfirm::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::MlmeStartCnf => Ok(MacEvent::MlmeStartCnf(StartConfirm::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::MlmePollCnf => Ok(MacEvent::MlmePollCnf(PollConfirm::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::MlmeDpsCnf => Ok(MacEvent::MlmeDpsCnf(DpsConfirm::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::MlmeSoundingCnf => { + Ok(MacEvent::MlmeSoundingCnf(SoundingConfirm::from_buffer(&payload[2..])?)) + } + OpcodeM0ToM4::MlmeCalibrateCnf => Ok(MacEvent::MlmeCalibrateCnf(CalibrateConfirm::from_buffer( + &payload[2..], + )?)), + OpcodeM0ToM4::McpsDataCnf => Ok(MacEvent::McpsDataCnf(DataConfirm::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::McpsPurgeCnf => Ok(MacEvent::McpsPurgeCnf(PurgeConfirm::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::MlmeAssociateInd => Ok(MacEvent::MlmeAssociateInd(AssociateIndication::from_buffer( + &payload[2..], + )?)), + OpcodeM0ToM4::MlmeDisassociateInd => Ok(MacEvent::MlmeDisassociateInd( + DisassociateIndication::from_buffer(&payload[2..])?, + )), + OpcodeM0ToM4::MlmeBeaconNotifyInd => Ok(MacEvent::MlmeBeaconNotifyInd( + BeaconNotifyIndication::from_buffer(&payload[2..])?, + )), + OpcodeM0ToM4::MlmeCommStatusInd => Ok(MacEvent::MlmeCommStatusInd(CommStatusIndication::from_buffer( + &payload[2..], + )?)), + OpcodeM0ToM4::MlmeGtsInd => Ok(MacEvent::MlmeGtsInd(GtsIndication::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::MlmeOrphanInd => Ok(MacEvent::MlmeOrphanInd(OrphanIndication::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::MlmeSyncLossInd => Ok(MacEvent::MlmeSyncLossInd(SyncLossIndication::from_buffer( + &payload[2..], + )?)), + OpcodeM0ToM4::MlmeDpsInd => Ok(MacEvent::MlmeDpsInd(DpsIndication::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::McpsDataInd => Ok(MacEvent::McpsDataInd(DataIndication::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::MlmePollInd => Ok(MacEvent::MlmePollInd(PollIndication::from_buffer(&payload[2..])?)), } } } + +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum MacEvent<'a> { + MlmeAssociateCnf(&'a AssociateConfirm), + MlmeDisassociateCnf(&'a DisassociateConfirm), + MlmeGetCnf(&'a GetConfirm), + MlmeGtsCnf(&'a GtsConfirm), + MlmeResetCnf(&'a ResetConfirm), + MlmeRxEnableCnf(&'a RxEnableConfirm), + MlmeScanCnf(&'a ScanConfirm), + MlmeSetCnf(&'a SetConfirm), + MlmeStartCnf(&'a StartConfirm), + MlmePollCnf(&'a PollConfirm), + MlmeDpsCnf(&'a DpsConfirm), + MlmeSoundingCnf(&'a SoundingConfirm), + MlmeCalibrateCnf(&'a CalibrateConfirm), + McpsDataCnf(&'a DataConfirm), + McpsPurgeCnf(&'a PurgeConfirm), + MlmeAssociateInd(&'a AssociateIndication), + MlmeDisassociateInd(&'a DisassociateIndication), + MlmeBeaconNotifyInd(&'a BeaconNotifyIndication), + MlmeCommStatusInd(&'a CommStatusIndication), + MlmeGtsInd(&'a GtsIndication), + MlmeOrphanInd(&'a OrphanIndication), + MlmeSyncLossInd(&'a SyncLossIndication), + MlmeDpsInd(&'a DpsIndication), + McpsDataInd(&'a DataIndication), + MlmePollInd(&'a PollIndication), +} diff --git a/embassy-stm32-wpan/src/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs index 436b9ac9..c7e9be84 100644 --- a/embassy-stm32-wpan/src/mac/indications.rs +++ b/embassy-stm32-wpan/src/mac/indications.rs @@ -23,22 +23,7 @@ pub struct AssociateIndication { pub key_source: [u8; 8], } -impl ParseableMacEvent for AssociateIndication { - const SIZE: usize = 20; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - device_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], - capability_information: Capabilities::from_bits(buf[8]).ok_or(())?, - security_level: SecurityLevel::try_from(buf[9])?, - key_id_mode: KeyIdMode::try_from(buf[10])?, - key_index: buf[11], - key_source: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]], - }) - } -} +impl ParseableMacEvent for AssociateIndication {} /// MLME DISASSOCIATE indication which will be used to send /// disassociation indication to the application. @@ -58,22 +43,7 @@ pub struct DisassociateIndication { pub key_source: [u8; 8], } -impl ParseableMacEvent for DisassociateIndication { - const SIZE: usize = 20; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - device_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], - disassociation_reason: DisassociationReason::try_from(buf[8])?, - security_level: SecurityLevel::try_from(buf[9])?, - key_id_mode: KeyIdMode::try_from(buf[10])?, - key_index: buf[11], - key_source: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]], - }) - } -} +impl ParseableMacEvent for DisassociateIndication {} /// MLME BEACON NOTIIFY Indication which is used to send parameters contained /// within a beacon frame received by the MAC to the application @@ -94,34 +64,7 @@ pub struct BeaconNotifyIndication { pub sdu_length: u8, } -impl ParseableMacEvent for BeaconNotifyIndication { - const SIZE: usize = 88; - - fn try_parse(buf: &[u8]) -> Result { - // TODO: this is unchecked - - Self::validate(buf)?; - - let addr_list = [ - MacAddress::try_from(&buf[26..34])?, - MacAddress::try_from(&buf[34..42])?, - MacAddress::try_from(&buf[42..50])?, - MacAddress::try_from(&buf[50..58])?, - MacAddress::try_from(&buf[58..66])?, - MacAddress::try_from(&buf[66..74])?, - MacAddress::try_from(&buf[74..82])?, - ]; - - Ok(Self { - sdu_ptr: u32::from_le_bytes(buf[0..4].try_into().unwrap()) as *const u8, - pan_descriptor: PanDescriptor::try_from(&buf[4..26])?, - addr_list, - bsn: buf[82], - pend_addr_spec: buf[83], - sdu_length: buf[83], - }) - } -} +impl ParseableMacEvent for BeaconNotifyIndication {} /// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -149,51 +92,7 @@ pub struct CommStatusIndication { pub key_source: [u8; 8], } -impl ParseableMacEvent for CommStatusIndication { - const SIZE: usize = 32; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - let src_addr_mode = AddressMode::try_from(buf[2])?; - let dst_addr_mode = AddressMode::try_from(buf[3])?; - - let src_address = match src_addr_mode { - AddressMode::NoAddress => MacAddress { short: [0, 0] }, - AddressMode::Reserved => MacAddress { short: [0, 0] }, - AddressMode::Short => MacAddress { - short: [buf[4], buf[5]], - }, - AddressMode::Extended => MacAddress { - extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], - }, - }; - - let dst_address = match dst_addr_mode { - AddressMode::NoAddress => MacAddress { short: [0, 0] }, - AddressMode::Reserved => MacAddress { short: [0, 0] }, - AddressMode::Short => MacAddress { - short: [buf[12], buf[13]], - }, - AddressMode::Extended => MacAddress { - extended: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]], - }, - }; - - Ok(Self { - pan_id: PanId([buf[0], buf[1]]), - src_addr_mode, - dst_addr_mode, - src_address, - dst_address, - status: MacStatus::try_from(buf[20])?, - security_level: SecurityLevel::try_from(buf[21])?, - key_id_mode: KeyIdMode::try_from(buf[22])?, - key_index: buf[23], - key_source: [buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31]], - }) - } -} +impl ParseableMacEvent for CommStatusIndication {} /// MLME GTS Indication indicates that a GTS has been allocated or that a /// previously allocated GTS has been deallocated @@ -209,27 +108,13 @@ pub struct GtsIndication { pub key_id_mode: KeyIdMode, /// Index of the key to be used pub key_index: u8, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 2], /// Originator of the key to be used pub key_source: [u8; 8], } -impl ParseableMacEvent for GtsIndication { - const SIZE: usize = 16; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - device_address: [buf[0], buf[1]], - gts_characteristics: buf[2], - security_level: SecurityLevel::try_from(buf[3])?, - key_id_mode: KeyIdMode::try_from(buf[4])?, - key_index: buf[5], - // 2 byte stuffing - key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]], - }) - } -} +impl ParseableMacEvent for GtsIndication {} /// MLME ORPHAN Indication which is used by the coordinator to notify the /// application of the presence of an orphaned device @@ -245,24 +130,11 @@ pub struct OrphanIndication { pub key_id_mode: KeyIdMode, /// Index of the key used by the originator of the received frame pub key_index: u8, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 1], } -impl ParseableMacEvent for OrphanIndication { - const SIZE: usize = 20; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - orphan_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], - key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]], - security_level: SecurityLevel::try_from(buf[16])?, - key_id_mode: KeyIdMode::try_from(buf[17])?, - key_index: buf[18], - // 1 byte stuffing - }) - } -} +impl ParseableMacEvent for OrphanIndication {} /// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss /// of synchronization with the coordinator @@ -286,42 +158,20 @@ pub struct SyncLossIndication { pub key_source: [u8; 8], } -impl ParseableMacEvent for SyncLossIndication { - const SIZE: usize = 16; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - pan_id: PanId([buf[0], buf[1]]), - loss_reason: buf[2], - channel_number: MacChannel::try_from(buf[3])?, - channel_page: buf[4], - security_level: SecurityLevel::try_from(buf[5])?, - key_id_mode: KeyIdMode::try_from(buf[6])?, - key_index: buf[7], - key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]], - }) - } -} +impl ParseableMacEvent for SyncLossIndication {} /// MLME DPS Indication which indicates the expiration of the DPSIndexDuration /// and the resetting of the DPS values in the PHY #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct DpsIndication; - -impl ParseableMacEvent for DpsIndication { - const SIZE: usize = 4; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self) - } +pub struct DpsIndication { + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 4], } +impl ParseableMacEvent for DpsIndication {} + #[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[repr(C, align(8))] +#[repr(C)] pub struct DataIndication { /// Pointer to the set of octets forming the MSDU being indicated pub msdu_ptr: *const u8, @@ -373,65 +223,7 @@ pub struct DataIndication { pub rssi: u8, } -impl ParseableMacEvent for DataIndication { - const SIZE: usize = 68; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - let src_addr_mode = AddressMode::try_from(buf[4])?; - let src_address = match src_addr_mode { - AddressMode::NoAddress => MacAddress { short: [0, 0] }, - AddressMode::Reserved => MacAddress { short: [0, 0] }, - AddressMode::Short => MacAddress { - short: [buf[7], buf[8]], - }, - AddressMode::Extended => MacAddress { - extended: [buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14]], - }, - }; - - let dst_addr_mode = AddressMode::try_from(buf[15])?; - let dst_address = match dst_addr_mode { - AddressMode::NoAddress => MacAddress { short: [0, 0] }, - AddressMode::Reserved => MacAddress { short: [0, 0] }, - AddressMode::Short => MacAddress { - short: [buf[18], buf[19]], - }, - AddressMode::Extended => MacAddress { - extended: [buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], buf[24], buf[25]], - }, - }; - - Ok(Self { - msdu_ptr: u32::from_le_bytes(buf[0..4].try_into().unwrap()) as *const u8, - src_addr_mode, - src_pan_id: PanId([buf[5], buf[6]]), - src_address, - dst_addr_mode, - dst_pan_id: PanId([buf[16], buf[17]]), - dst_address, - msdu_length: buf[26], - mpdu_link_quality: buf[27], - dsn: buf[28], - time_stamp: [buf[29], buf[30], buf[31], buf[32]], - security_level: SecurityLevel::try_from(buf[33]).unwrap_or(SecurityLevel::Unsecure), // TODO: this is totaly wrong, but I'm too smol brain to fix it - key_id_mode: KeyIdMode::try_from(buf[34]).unwrap_or(KeyIdMode::Implicite), // TODO: this is totaly wrong, but I'm too smol brain to fix it - key_source: [buf[35], buf[36], buf[37], buf[38], buf[39], buf[40], buf[41], buf[42]], - key_index: buf[43], - uwbprf: buf[44], - uwn_preamble_symbol_repetitions: buf[45], - datrate: buf[46], - ranging_received: buf[47], - ranging_counter_start: u32::from_le_bytes(buf[48..52].try_into().unwrap()), - ranging_counter_stop: u32::from_le_bytes(buf[52..56].try_into().unwrap()), - ranging_tracking_interval: u32::from_le_bytes(buf[56..60].try_into().unwrap()), - ranging_offset: u32::from_le_bytes(buf[60..64].try_into().unwrap()), - ranging_fom: buf[65], - rssi: buf[66], - }) - } -} +impl ParseableMacEvent for DataIndication {} /// MLME POLL Indication which will be used for indicating the Data Request /// reception to upper layer as defined in Zigbee r22 - D.8.2 @@ -443,27 +235,4 @@ pub struct PollIndication { pub request_address: MacAddress, } -impl ParseableMacEvent for PollIndication { - const SIZE: usize = 9; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - let addr_mode = AddressMode::try_from(buf[0])?; - let request_address = match addr_mode { - AddressMode::NoAddress => MacAddress { short: [0, 0] }, - AddressMode::Reserved => MacAddress { short: [0, 0] }, - AddressMode::Short => MacAddress { - short: [buf[1], buf[2]], - }, - AddressMode::Extended => MacAddress { - extended: [buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]], - }, - }; - - Ok(Self { - addr_mode, - request_address, - }) - } -} +impl ParseableMacEvent for PollIndication {} diff --git a/embassy-stm32-wpan/src/mac/responses.rs b/embassy-stm32-wpan/src/mac/responses.rs index d29257f8..e0376a7f 100644 --- a/embassy-stm32-wpan/src/mac/responses.rs +++ b/embassy-stm32-wpan/src/mac/responses.rs @@ -21,24 +21,11 @@ pub struct AssociateConfirm { pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 2], } -impl ParseableMacEvent for AssociateConfirm { - const SIZE: usize = 16; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - assoc_short_address: [buf[0], buf[1]], - status: AssociationStatus::try_from(buf[2])?, - security_level: SecurityLevel::try_from(buf[3])?, - key_source: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], - key_id_mode: KeyIdMode::try_from(buf[12])?, - key_index: buf[13], - }) - } -} +impl ParseableMacEvent for AssociateConfirm {} /// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application. #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -53,32 +40,7 @@ pub struct DisassociateConfirm { pub device_address: MacAddress, } -impl ParseableMacEvent for DisassociateConfirm { - const SIZE: usize = 12; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - let device_addr_mode = AddressMode::try_from(buf[1])?; - let device_address = match device_addr_mode { - AddressMode::NoAddress => MacAddress { short: [0, 0] }, - AddressMode::Reserved => MacAddress { short: [0, 0] }, - AddressMode::Short => MacAddress { - short: [buf[4], buf[5]], - }, - AddressMode::Extended => MacAddress { - extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], - }, - }; - - Ok(Self { - status: MacStatus::try_from(buf[0])?, - device_addr_mode, - device_pan_id: PanId([buf[2], buf[3]]), - device_address, - }) - } -} +impl ParseableMacEvent for DisassociateConfirm {} /// MLME GET Confirm which requests information about a given PIB attribute #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -91,24 +53,11 @@ pub struct GetConfirm { pub pib_attribute: PibId, /// The lenght of the PIB attribute Value return pub pib_attribute_value_len: u8, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 1], } -impl ParseableMacEvent for GetConfirm { - const SIZE: usize = 8; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - let address = u32::from_le_bytes(buf[0..4].try_into().unwrap()); - - Ok(Self { - pib_attribute_value_ptr: address as *const u8, - status: MacStatus::try_from(buf[4])?, - pib_attribute: PibId::try_from(buf[5])?, - pib_attribute_value_len: buf[6], - }) - } -} +impl ParseableMacEvent for GetConfirm {} /// MLME GTS Confirm which eports the results of a request to allocate a new GTS /// or to deallocate an existing GTS @@ -118,39 +67,22 @@ pub struct GtsConfirm { pub gts_characteristics: u8, /// The status of the GTS reques pub status: MacStatus, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 2], } -impl ParseableMacEvent for GtsConfirm { - const SIZE: usize = 4; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - gts_characteristics: buf[0], - status: MacStatus::try_from(buf[1])?, - }) - } -} +impl ParseableMacEvent for GtsConfirm {} /// MLME RESET Confirm which is used to report the results of the reset operation #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ResetConfirm { /// The result of the reset operation status: MacStatus, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 3], } -impl ParseableMacEvent for ResetConfirm { - const SIZE: usize = 4; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - status: MacStatus::try_from(buf[0])?, - }) - } -} +impl ParseableMacEvent for ResetConfirm {} /// MLME RX ENABLE Confirm which is used to report the results of the attempt /// to enable or disable the receiver @@ -158,19 +90,11 @@ impl ParseableMacEvent for ResetConfirm { pub struct RxEnableConfirm { /// Result of the request to enable or disable the receiver status: MacStatus, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 3], } -impl ParseableMacEvent for RxEnableConfirm { - const SIZE: usize = 4; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - status: MacStatus::try_from(buf[0])?, - }) - } -} +impl ParseableMacEvent for RxEnableConfirm {} /// MLME SCAN Confirm which is used to report the result of the channel scan request #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -195,42 +119,7 @@ pub struct ScanConfirm { pub uwb_energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED], } -impl ParseableMacEvent for ScanConfirm { - const SIZE: usize = 185; - - fn try_parse(buf: &[u8]) -> Result { - // TODO: this is unchecked - - Self::validate(buf)?; - - let mut energy_detect_list = [0; MAX_ED_SCAN_RESULTS_SUPPORTED]; - energy_detect_list.copy_from_slice(&buf[8..24]); - - let pan_descriptor_list = [ - PanDescriptor::try_from(&buf[24..46])?, - PanDescriptor::try_from(&buf[46..68])?, - PanDescriptor::try_from(&buf[68..90])?, - PanDescriptor::try_from(&buf[90..102])?, - PanDescriptor::try_from(&buf[102..124])?, - PanDescriptor::try_from(&buf[124..146])?, - ]; - - let mut uwb_energy_detect_list = [0; MAX_ED_SCAN_RESULTS_SUPPORTED]; - uwb_energy_detect_list.copy_from_slice(&buf[147..163]); - - Ok(Self { - status: MacStatus::try_from(buf[0])?, - scan_type: ScanType::try_from(buf[1])?, - channel_page: buf[2], - unscanned_channels: [buf[3], buf[4], buf[5], buf[6]], - result_list_size: buf[7], - energy_detect_list, - pan_descriptor_list, - detected_category: buf[146], - uwb_energy_detect_list, - }) - } -} +impl ParseableMacEvent for ScanConfirm {} /// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -239,20 +128,11 @@ pub struct SetConfirm { pub status: MacStatus, /// The name of the PIB attribute that was written pub pin_attribute: PibId, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 2], } -impl ParseableMacEvent for SetConfirm { - const SIZE: usize = 4; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - status: MacStatus::try_from(buf[0])?, - pin_attribute: PibId::try_from(buf[1])?, - }) - } -} +impl ParseableMacEvent for SetConfirm {} /// MLME START Confirm which is used to report the results of the attempt to /// start using a new superframe configuration @@ -260,57 +140,33 @@ impl ParseableMacEvent for SetConfirm { pub struct StartConfirm { /// Result of the attempt to start using an updated superframe configuration pub status: MacStatus, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 3], } -impl ParseableMacEvent for StartConfirm { - const SIZE: usize = 4; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - status: MacStatus::try_from(buf[0])?, - }) - } -} +impl ParseableMacEvent for StartConfirm {} /// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PollConfirm { /// The status of the data request pub status: MacStatus, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 3], } -impl ParseableMacEvent for PollConfirm { - const SIZE: usize = 4; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - status: MacStatus::try_from(buf[0])?, - }) - } -} +impl ParseableMacEvent for PollConfirm {} /// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DpsConfirm { /// The status of the DPS request pub status: MacStatus, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 3], } -impl ParseableMacEvent for DpsConfirm { - const SIZE: usize = 4; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - status: MacStatus::try_from(buf[0])?, - }) - } -} +impl ParseableMacEvent for DpsConfirm {} /// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide /// channel sounding information @@ -318,20 +174,11 @@ impl ParseableMacEvent for DpsConfirm { pub struct SoundingConfirm { /// Results of the sounding measurement sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED], + + status: u8, } -impl ParseableMacEvent for SoundingConfirm { - const SIZE: usize = 1; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - let mut sounding_list = [0u8; MAX_SOUNDING_LIST_SUPPORTED]; - sounding_list[..buf.len()].copy_from_slice(buf); - - Ok(Self { sounding_list }) - } -} +impl ParseableMacEvent for SoundingConfirm {} /// MLME CALIBRATE Confirm which reports the result of a request to the PHY /// to provide internal propagation path information @@ -339,6 +186,8 @@ impl ParseableMacEvent for SoundingConfirm { pub struct CalibrateConfirm { /// The status of the attempt to return sounding data pub status: MacStatus, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 3], /// A count of the propagation time from the ranging counter /// to the transmit antenna pub cal_tx_rmaker_offset: u32, @@ -347,20 +196,7 @@ pub struct CalibrateConfirm { pub cal_rx_rmaker_offset: u32, } -impl ParseableMacEvent for CalibrateConfirm { - const SIZE: usize = 12; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - status: MacStatus::try_from(buf[0])?, - // 3 byte stuffing - cal_tx_rmaker_offset: u32::from_le_bytes(buf[4..8].try_into().unwrap()), - cal_rx_rmaker_offset: u32::from_le_bytes(buf[8..12].try_into().unwrap()), - }) - } -} +impl ParseableMacEvent for CalibrateConfirm {} /// MCPS DATA Confirm which will be used for reporting the results of /// MAC data related requests from the application @@ -386,27 +222,11 @@ pub struct DataConfirm { pub ranging_offset: u32, /// The FoM characterizing the ranging measurement pub ranging_fom: u8, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 3], } -impl ParseableMacEvent for DataConfirm { - const SIZE: usize = 28; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - msdu_handle: buf[0], - time_stamp: [buf[1], buf[2], buf[3], buf[4]], - ranging_received: buf[5], - status: MacStatus::try_from(buf[6])?, - ranging_counter_start: u32::from_le_bytes(buf[7..11].try_into().unwrap()), - ranging_counter_stop: u32::from_le_bytes(buf[11..15].try_into().unwrap()), - ranging_tracking_interval: u32::from_le_bytes(buf[15..19].try_into().unwrap()), - ranging_offset: u32::from_le_bytes(buf[19..23].try_into().unwrap()), - ranging_fom: buf[24], - }) - } -} +impl ParseableMacEvent for DataConfirm {} /// MCPS PURGE Confirm which will be used by the MAC to notify the application of /// the status of its request to purge an MSDU from the transaction queue @@ -416,17 +236,8 @@ pub struct PurgeConfirm { pub msdu_handle: u8, /// The status of the request pub status: MacStatus, + /// byte stuffing to keep 32 bit alignment + a_stuffing: [u8; 2], } -impl ParseableMacEvent for PurgeConfirm { - const SIZE: usize = 4; - - fn try_parse(buf: &[u8]) -> Result { - Self::validate(buf)?; - - Ok(Self { - msdu_handle: buf[0], - status: MacStatus::try_from(buf[1])?, - }) - } -} +impl ParseableMacEvent for PurgeConfirm {} diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs index d30ed2f1..d9bf4c90 100644 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ b/embassy-stm32-wpan/src/sub/mac.rs @@ -12,7 +12,7 @@ use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::{EvtBox, EvtPacket}; use crate::mac::commands::MacCommand; -use crate::mac::event::MacEvent; +use crate::mac::event::Event; use crate::mac::typedefs::MacError; use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; use crate::{channels, evt}; @@ -94,11 +94,8 @@ impl Mac { } } - pub async fn read(&self) -> Result { - let evt_box = self.tl_read().await; - let payload = evt_box.payload(); - - MacEvent::try_from(payload) + pub async fn read(&self) -> Event { + Event::new(self.tl_read().await) } } diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index f8c8ba28..86413ea0 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -73,8 +73,10 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } info!("setting extended address"); let extended_address: u64 = 0xACDE480000000001; @@ -85,8 +87,10 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } info!("setting short address"); let short_address: u16 = 0x1122; @@ -97,8 +101,10 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } info!("setting association permit"); let association_permit: bool = true; @@ -109,8 +115,10 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } info!("setting TX power"); let transmit_power: i8 = 2; @@ -121,8 +129,10 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } info!("starting FFD device"); mbox.mac_subsystem @@ -137,8 +147,10 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } info!("setting RX on when idle"); let rx_on_while_idle: bool = true; @@ -149,14 +161,16 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } loop { let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt); + defmt::info!("{:#x}", evt.mac_event()); - if let Ok(evt) = evt { + if let Ok(evt) = evt.mac_event() { match evt { MacEvent::MlmeAssociateInd(association) => mbox .mac_subsystem diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index b0eb9106..7cb401d8 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -75,8 +75,10 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } info!("setting extended address"); let extended_address: u64 = 0xACDE480000000002; @@ -87,8 +89,10 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } info!("getting extended address"); mbox.mac_subsystem @@ -98,14 +102,17 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt); - if let Ok(MacEvent::MlmeGetCnf(evt)) = evt { - if evt.pib_attribute_value_len == 8 { - let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; + { + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt.mac_event()); - info!("value {:#x}", value) + if let Ok(MacEvent::MlmeGetCnf(evt)) = evt.mac_event() { + if evt.pib_attribute_value_len == 8 { + let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; + + info!("value {:#x}", value) + } } } @@ -124,13 +131,15 @@ async fn main(spawner: Spawner) { }; info!("{}", a); mbox.mac_subsystem.send_command(&a).await.unwrap(); - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt); + let short_addr = { + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt.mac_event()); - let short_addr = if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt { - conf.assoc_short_address - } else { - defmt::panic!() + if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt.mac_event() { + conf.assoc_short_address + } else { + defmt::panic!() + } }; info!("setting short address"); @@ -141,8 +150,10 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt.mac_event()); + } info!("sending data"); let data = b"Hello from embassy!"; @@ -163,11 +174,13 @@ async fn main(spawner: Spawner) { ) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt.mac_event()); + } loop { let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt); + info!("{:#x}", evt.mac_event()); } } diff --git a/tests/stm32/src/bin/wpan_mac.rs b/tests/stm32/src/bin/wpan_mac.rs index 2fc15dc9..d64a5ef8 100644 --- a/tests/stm32/src/bin/wpan_mac.rs +++ b/tests/stm32/src/bin/wpan_mac.rs @@ -55,8 +55,10 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt.mac_event()); + } info!("setting extended address"); let extended_address: u64 = 0xACDE480000000002; @@ -67,8 +69,10 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt.mac_event()); + } info!("getting extended address"); mbox.mac_subsystem @@ -78,14 +82,16 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt.mac_event()); - if let Ok(MacEvent::MlmeGetCnf(evt)) = evt { - if evt.pib_attribute_value_len == 8 { - let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; + if let Ok(MacEvent::MlmeGetCnf(evt)) = evt.mac_event() { + if evt.pib_attribute_value_len == 8 { + let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; - info!("value {:#x}", value) + info!("value {:#x}", value) + } } } @@ -104,8 +110,10 @@ async fn main(spawner: Spawner) { }; info!("{}", a); mbox.mac_subsystem.send_command(&a).await.unwrap(); - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt); + { + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt.mac_event()); + } info!("Test OK"); cortex_m::asm::bkpt(); From a0515ca7ac9f4aebeadede7c6a2fa312b60b5d55 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 16 Jul 2023 16:16:56 -0500 Subject: [PATCH 112/148] wpan: add repr(c) to mac responses --- embassy-stm32-wpan/src/mac/indications.rs | 11 ++++++++++- embassy-stm32-wpan/src/mac/responses.rs | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/embassy-stm32-wpan/src/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs index c7e9be84..66819dc9 100644 --- a/embassy-stm32-wpan/src/mac/indications.rs +++ b/embassy-stm32-wpan/src/mac/indications.rs @@ -7,6 +7,7 @@ use super::typedefs::{ /// MLME ASSOCIATE Indication which will be used by the MAC /// to indicate the reception of an association request command +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateIndication { /// Extended address of the device requesting association @@ -27,6 +28,7 @@ impl ParseableMacEvent for AssociateIndication {} /// MLME DISASSOCIATE indication which will be used to send /// disassociation indication to the application. +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DisassociateIndication { /// Extended address of the device requesting association @@ -47,6 +49,7 @@ impl ParseableMacEvent for DisassociateIndication {} /// MLME BEACON NOTIIFY Indication which is used to send parameters contained /// within a beacon frame received by the MAC to the application +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct BeaconNotifyIndication { /// he set of octets comprising the beacon payload to be transferred @@ -67,6 +70,7 @@ pub struct BeaconNotifyIndication { impl ParseableMacEvent for BeaconNotifyIndication {} /// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CommStatusIndication { /// The 16-bit PAN identifier of the device from which the frame @@ -96,6 +100,7 @@ impl ParseableMacEvent for CommStatusIndication {} /// MLME GTS Indication indicates that a GTS has been allocated or that a /// previously allocated GTS has been deallocated +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsIndication { /// The short address of the device that has been allocated or deallocated a GTS @@ -118,6 +123,7 @@ impl ParseableMacEvent for GtsIndication {} /// MLME ORPHAN Indication which is used by the coordinator to notify the /// application of the presence of an orphaned device +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct OrphanIndication { /// Extended address of the orphaned device @@ -138,6 +144,7 @@ impl ParseableMacEvent for OrphanIndication {} /// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss /// of synchronization with the coordinator +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SyncLossIndication { /// The PAN identifier with which the device lost synchronization or to which it was realigned @@ -162,6 +169,7 @@ impl ParseableMacEvent for SyncLossIndication {} /// MLME DPS Indication which indicates the expiration of the DPSIndexDuration /// and the resetting of the DPS values in the PHY +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DpsIndication { /// byte stuffing to keep 32 bit alignment @@ -170,8 +178,8 @@ pub struct DpsIndication { impl ParseableMacEvent for DpsIndication {} -#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DataIndication { /// Pointer to the set of octets forming the MSDU being indicated pub msdu_ptr: *const u8, @@ -227,6 +235,7 @@ impl ParseableMacEvent for DataIndication {} /// MLME POLL Indication which will be used for indicating the Data Request /// reception to upper layer as defined in Zigbee r22 - D.8.2 +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PollIndication { /// addressing mode used diff --git a/embassy-stm32-wpan/src/mac/responses.rs b/embassy-stm32-wpan/src/mac/responses.rs index e0376a7f..5d203084 100644 --- a/embassy-stm32-wpan/src/mac/responses.rs +++ b/embassy-stm32-wpan/src/mac/responses.rs @@ -7,6 +7,7 @@ use super::typedefs::{ /// MLME ASSOCIATE Confirm used to inform of the initiating device whether /// its request to associate was successful or unsuccessful +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateConfirm { /// short address allocated by the coordinator on successful association @@ -28,6 +29,7 @@ pub struct AssociateConfirm { impl ParseableMacEvent for AssociateConfirm {} /// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application. +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DisassociateConfirm { /// status of the disassociation attempt @@ -43,6 +45,7 @@ pub struct DisassociateConfirm { impl ParseableMacEvent for DisassociateConfirm {} /// MLME GET Confirm which requests information about a given PIB attribute +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GetConfirm { /// The pointer to the value of the PIB attribute attempted to read @@ -61,6 +64,7 @@ impl ParseableMacEvent for GetConfirm {} /// MLME GTS Confirm which eports the results of a request to allocate a new GTS /// or to deallocate an existing GTS +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsConfirm { /// The characteristics of the GTS @@ -74,6 +78,7 @@ pub struct GtsConfirm { impl ParseableMacEvent for GtsConfirm {} /// MLME RESET Confirm which is used to report the results of the reset operation +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ResetConfirm { /// The result of the reset operation @@ -86,6 +91,7 @@ impl ParseableMacEvent for ResetConfirm {} /// MLME RX ENABLE Confirm which is used to report the results of the attempt /// to enable or disable the receiver +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct RxEnableConfirm { /// Result of the request to enable or disable the receiver @@ -97,6 +103,7 @@ pub struct RxEnableConfirm { impl ParseableMacEvent for RxEnableConfirm {} /// MLME SCAN Confirm which is used to report the result of the channel scan request +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ScanConfirm { /// Status of the scan request @@ -122,6 +129,7 @@ pub struct ScanConfirm { impl ParseableMacEvent for ScanConfirm {} /// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SetConfirm { /// The result of the set operation @@ -136,6 +144,7 @@ impl ParseableMacEvent for SetConfirm {} /// MLME START Confirm which is used to report the results of the attempt to /// start using a new superframe configuration +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct StartConfirm { /// Result of the attempt to start using an updated superframe configuration @@ -147,6 +156,7 @@ pub struct StartConfirm { impl ParseableMacEvent for StartConfirm {} /// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PollConfirm { /// The status of the data request @@ -158,6 +168,7 @@ pub struct PollConfirm { impl ParseableMacEvent for PollConfirm {} /// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DpsConfirm { /// The status of the DPS request @@ -170,6 +181,7 @@ impl ParseableMacEvent for DpsConfirm {} /// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide /// channel sounding information +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SoundingConfirm { /// Results of the sounding measurement @@ -182,6 +194,7 @@ impl ParseableMacEvent for SoundingConfirm {} /// MLME CALIBRATE Confirm which reports the result of a request to the PHY /// to provide internal propagation path information +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CalibrateConfirm { /// The status of the attempt to return sounding data @@ -200,6 +213,7 @@ impl ParseableMacEvent for CalibrateConfirm {} /// MCPS DATA Confirm which will be used for reporting the results of /// MAC data related requests from the application +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DataConfirm { /// The handle associated with the MSDU being confirmed @@ -230,6 +244,7 @@ impl ParseableMacEvent for DataConfirm {} /// MCPS PURGE Confirm which will be used by the MAC to notify the application of /// the status of its request to purge an MSDU from the transaction queue +#[repr(C)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PurgeConfirm { /// Handle associated with the MSDU requested to be purged from the transaction queue From 34217ea797c6bbea6219bb2bc2b611a99212e14b Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 16 Jul 2023 17:28:34 -0500 Subject: [PATCH 113/148] wpan: add slice data view --- embassy-stm32-wpan/src/mac/event.rs | 73 ++++++++++------------- embassy-stm32-wpan/src/mac/indications.rs | 8 +++ examples/stm32wb/src/bin/mac_ffd.rs | 22 ++++--- 3 files changed, 52 insertions(+), 51 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs index 67f207d5..a2bb7922 100644 --- a/embassy-stm32-wpan/src/mac/event.rs +++ b/embassy-stm32-wpan/src/mac/event.rs @@ -36,53 +36,40 @@ impl Event { let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap()); let opcode = OpcodeM0ToM4::try_from(opcode)?; + let buf = &payload[2..]; match opcode { - OpcodeM0ToM4::MlmeAssociateCnf => Ok(MacEvent::MlmeAssociateCnf(AssociateConfirm::from_buffer( - &payload[2..], - )?)), - OpcodeM0ToM4::MlmeDisassociateCnf => Ok(MacEvent::MlmeDisassociateCnf(DisassociateConfirm::from_buffer( - &payload[2..], - )?)), - OpcodeM0ToM4::MlmeGetCnf => Ok(MacEvent::MlmeGetCnf(GetConfirm::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::MlmeGtsCnf => Ok(MacEvent::MlmeGtsCnf(GtsConfirm::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::MlmeResetCnf => Ok(MacEvent::MlmeResetCnf(ResetConfirm::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::MlmeRxEnableCnf => { - Ok(MacEvent::MlmeRxEnableCnf(RxEnableConfirm::from_buffer(&payload[2..])?)) + OpcodeM0ToM4::MlmeAssociateCnf => Ok(MacEvent::MlmeAssociateCnf(AssociateConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeDisassociateCnf => { + Ok(MacEvent::MlmeDisassociateCnf(DisassociateConfirm::from_buffer(buf)?)) } - OpcodeM0ToM4::MlmeScanCnf => Ok(MacEvent::MlmeScanCnf(ScanConfirm::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::MlmeSetCnf => Ok(MacEvent::MlmeSetCnf(SetConfirm::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::MlmeStartCnf => Ok(MacEvent::MlmeStartCnf(StartConfirm::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::MlmePollCnf => Ok(MacEvent::MlmePollCnf(PollConfirm::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::MlmeDpsCnf => Ok(MacEvent::MlmeDpsCnf(DpsConfirm::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::MlmeSoundingCnf => { - Ok(MacEvent::MlmeSoundingCnf(SoundingConfirm::from_buffer(&payload[2..])?)) + OpcodeM0ToM4::MlmeGetCnf => Ok(MacEvent::MlmeGetCnf(GetConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeGtsCnf => Ok(MacEvent::MlmeGtsCnf(GtsConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeResetCnf => Ok(MacEvent::MlmeResetCnf(ResetConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeRxEnableCnf => Ok(MacEvent::MlmeRxEnableCnf(RxEnableConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeScanCnf => Ok(MacEvent::MlmeScanCnf(ScanConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeSetCnf => Ok(MacEvent::MlmeSetCnf(SetConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeStartCnf => Ok(MacEvent::MlmeStartCnf(StartConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::MlmePollCnf => Ok(MacEvent::MlmePollCnf(PollConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeDpsCnf => Ok(MacEvent::MlmeDpsCnf(DpsConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeSoundingCnf => Ok(MacEvent::MlmeSoundingCnf(SoundingConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeCalibrateCnf => Ok(MacEvent::MlmeCalibrateCnf(CalibrateConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::McpsDataCnf => Ok(MacEvent::McpsDataCnf(DataConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::McpsPurgeCnf => Ok(MacEvent::McpsPurgeCnf(PurgeConfirm::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeAssociateInd => Ok(MacEvent::MlmeAssociateInd(AssociateIndication::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeDisassociateInd => { + Ok(MacEvent::MlmeDisassociateInd(DisassociateIndication::from_buffer(buf)?)) } - OpcodeM0ToM4::MlmeCalibrateCnf => Ok(MacEvent::MlmeCalibrateCnf(CalibrateConfirm::from_buffer( - &payload[2..], - )?)), - OpcodeM0ToM4::McpsDataCnf => Ok(MacEvent::McpsDataCnf(DataConfirm::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::McpsPurgeCnf => Ok(MacEvent::McpsPurgeCnf(PurgeConfirm::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::MlmeAssociateInd => Ok(MacEvent::MlmeAssociateInd(AssociateIndication::from_buffer( - &payload[2..], - )?)), - OpcodeM0ToM4::MlmeDisassociateInd => Ok(MacEvent::MlmeDisassociateInd( - DisassociateIndication::from_buffer(&payload[2..])?, - )), - OpcodeM0ToM4::MlmeBeaconNotifyInd => Ok(MacEvent::MlmeBeaconNotifyInd( - BeaconNotifyIndication::from_buffer(&payload[2..])?, - )), - OpcodeM0ToM4::MlmeCommStatusInd => Ok(MacEvent::MlmeCommStatusInd(CommStatusIndication::from_buffer( - &payload[2..], - )?)), - OpcodeM0ToM4::MlmeGtsInd => Ok(MacEvent::MlmeGtsInd(GtsIndication::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::MlmeOrphanInd => Ok(MacEvent::MlmeOrphanInd(OrphanIndication::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::MlmeSyncLossInd => Ok(MacEvent::MlmeSyncLossInd(SyncLossIndication::from_buffer( - &payload[2..], - )?)), - OpcodeM0ToM4::MlmeDpsInd => Ok(MacEvent::MlmeDpsInd(DpsIndication::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::McpsDataInd => Ok(MacEvent::McpsDataInd(DataIndication::from_buffer(&payload[2..])?)), - OpcodeM0ToM4::MlmePollInd => Ok(MacEvent::MlmePollInd(PollIndication::from_buffer(&payload[2..])?)), + OpcodeM0ToM4::MlmeBeaconNotifyInd => { + Ok(MacEvent::MlmeBeaconNotifyInd(BeaconNotifyIndication::from_buffer(buf)?)) + } + OpcodeM0ToM4::MlmeCommStatusInd => Ok(MacEvent::MlmeCommStatusInd(CommStatusIndication::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeGtsInd => Ok(MacEvent::MlmeGtsInd(GtsIndication::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeOrphanInd => Ok(MacEvent::MlmeOrphanInd(OrphanIndication::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeSyncLossInd => Ok(MacEvent::MlmeSyncLossInd(SyncLossIndication::from_buffer(buf)?)), + OpcodeM0ToM4::MlmeDpsInd => Ok(MacEvent::MlmeDpsInd(DpsIndication::from_buffer(buf)?)), + OpcodeM0ToM4::McpsDataInd => Ok(MacEvent::McpsDataInd(DataIndication::from_buffer(buf)?)), + OpcodeM0ToM4::MlmePollInd => Ok(MacEvent::MlmePollInd(PollIndication::from_buffer(buf)?)), } } } diff --git a/embassy-stm32-wpan/src/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs index 66819dc9..cf795dfa 100644 --- a/embassy-stm32-wpan/src/mac/indications.rs +++ b/embassy-stm32-wpan/src/mac/indications.rs @@ -1,3 +1,5 @@ +use core::slice; + use super::consts::MAX_PENDING_ADDRESS; use super::event::ParseableMacEvent; use super::typedefs::{ @@ -233,6 +235,12 @@ pub struct DataIndication { impl ParseableMacEvent for DataIndication {} +impl DataIndication { + pub fn payload<'a>(&'a self) -> &'a [u8] { + unsafe { slice::from_raw_parts(self.msdu_ptr as *const _ as *const u8, self.msdu_length as usize) } + } +} + /// MLME POLL Indication which will be used for indicating the Data Request /// reception to upper layer as defined in Zigbee r22 - D.8.2 #[repr(C)] diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 86413ea0..bc71e29a 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -168,9 +168,10 @@ async fn main(spawner: Spawner) { loop { let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); - if let Ok(evt) = evt.mac_event() { + defmt::info!("parsed mac event"); + defmt::info!("{:#x}", evt); + match evt { MacEvent::MlmeAssociateInd(association) => mbox .mac_subsystem @@ -184,17 +185,22 @@ async fn main(spawner: Spawner) { .await .unwrap(), MacEvent::McpsDataInd(data_ind) => { - let data_addr = data_ind.msdu_ptr; - let mut data = [0u8; 256]; - unsafe { data_addr.copy_to(&mut data as *mut _, data_ind.msdu_length as usize) } - info!("{}", data[..data_ind.msdu_length as usize]); + let payload = data_ind.payload(); + let ref_payload = b"Hello from embassy!"; + info!("{}", payload); - if &data[..data_ind.msdu_length as usize] == b"Hello from embassy!" { + if payload == ref_payload { info!("success"); + } else { + info!("ref payload: {}", ref_payload); } } - _ => {} + _ => { + defmt::info!("other mac event"); + } } + } else { + defmt::info!("failed to parse mac event"); } } } From fe1e7c4d7660163457226316ffbf30f6f3c8ddc5 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 16 Jul 2023 18:07:05 -0500 Subject: [PATCH 114/148] wpan: fix datarequest --- embassy-stm32-wpan/src/mac/commands.rs | 2 +- embassy-stm32-wpan/src/mac/indications.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/commands.rs b/embassy-stm32-wpan/src/mac/commands.rs index 8acae24b..8f6dcbbb 100644 --- a/embassy-stm32-wpan/src/mac/commands.rs +++ b/embassy-stm32-wpan/src/mac/commands.rs @@ -370,7 +370,7 @@ pub struct DataRequest { impl DataRequest { pub fn set_buffer<'a>(&'a mut self, buf: &'a [u8]) -> &mut Self { - self.msdu_ptr = &buf as *const _ as *const u8; + self.msdu_ptr = buf as *const _ as *const u8; self.msdu_length = buf.len() as u8; self diff --git a/embassy-stm32-wpan/src/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs index cf795dfa..98826e66 100644 --- a/embassy-stm32-wpan/src/mac/indications.rs +++ b/embassy-stm32-wpan/src/mac/indications.rs @@ -237,7 +237,7 @@ impl ParseableMacEvent for DataIndication {} impl DataIndication { pub fn payload<'a>(&'a self) -> &'a [u8] { - unsafe { slice::from_raw_parts(self.msdu_ptr as *const _ as *const u8, self.msdu_length as usize) } + unsafe { slice::from_raw_parts(self.msdu_ptr, self.msdu_length as usize) } } } From 7b34f5e866958f2ff28d7deb6888666690fe2837 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 16 Jul 2023 18:54:11 -0500 Subject: [PATCH 115/148] wpan: make dataind fields private --- embassy-stm32-wpan/src/mac/indications.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs index 98826e66..5445fb4a 100644 --- a/embassy-stm32-wpan/src/mac/indications.rs +++ b/embassy-stm32-wpan/src/mac/indications.rs @@ -206,9 +206,9 @@ pub struct DataIndication { /// The time, in symbols, at which the data were received pub time_stamp: [u8; 4], /// The security level purportedly used by the received data frame - pub security_level: SecurityLevel, + security_level: SecurityLevel, /// Mode used to identify the key used by originator of received frame - pub key_id_mode: KeyIdMode, + key_id_mode: KeyIdMode, /// The originator of the key pub key_source: [u8; 8], /// The index of the key From e4ad1aa542ad28bed23532b3a0bee0d062454516 Mon Sep 17 00:00:00 2001 From: Alex Ferro Date: Sun, 16 Jul 2023 19:59:35 -0600 Subject: [PATCH 116/148] Embassy-rp I2C: Fix 1664 Change embassy-rp i2c.rs impl of embedded_hal_async::i2c::I2c::transaction to only do the call to setup() for address once per call to transactions. Calling setup multiple times results in I2C transactions being skipped on the bus, even across calls to transaction() or devices. --- embassy-rp/src/i2c.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index 791c6455..9b85b234 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -716,6 +716,9 @@ mod nightly { async fn transaction(&mut self, address: A, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> { let addr: u16 = address.into(); + if operations.len() > 0 { + Self::setup(addr)?; + } let mut iterator = operations.iter_mut(); while let Some(op) = iterator.next() { @@ -723,11 +726,9 @@ mod nightly { match op { Operation::Read(buffer) => { - Self::setup(addr)?; self.read_async_internal(buffer, false, last).await?; } Operation::Write(buffer) => { - Self::setup(addr)?; self.write_async_internal(buffer.into_iter().cloned(), last).await?; } } From 55ac480cb000b466571feee712d4ff075a1c64f8 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 17 Jul 2023 16:24:09 -0500 Subject: [PATCH 117/148] stm32/eth: fix cfg(not(time)) --- embassy-stm32/src/eth/generic_smi.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 90631b17..2ed46ca2 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs @@ -45,20 +45,19 @@ use self::phy_consts::*; pub struct GenericSMI { #[cfg(feature = "time")] poll_interval: Duration, + #[cfg(not(feature = "time"))] + _private: (), } impl GenericSMI { - #[cfg(feature = "time")] pub fn new() -> Self { Self { + #[cfg(feature = "time")] poll_interval: Duration::from_millis(500), + #[cfg(not(feature = "time"))] + _private: (), } } - - #[cfg(not(feature = "time"))] - pub fn new() -> Self { - Self {} - } } unsafe impl PHY for GenericSMI { @@ -102,6 +101,7 @@ unsafe impl PHY for GenericSMI { /// Public functions for the PHY impl GenericSMI { + #[cfg(feature = "time")] pub fn set_poll_interval(&mut self, poll_interval: Duration) { self.poll_interval = poll_interval } From 8f23b6faa6f04f83ece119e94335f892d516f6b3 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 17 Jul 2023 19:26:58 -0500 Subject: [PATCH 118/148] wpan: refactor control, driver --- embassy-stm32-wpan/src/mac/control.rs | 446 +------------------------- embassy-stm32-wpan/src/mac/driver.rs | 160 ++++----- embassy-stm32-wpan/src/mac/event.rs | 120 ------- embassy-stm32-wpan/src/mac/ioctl.rs | 124 ------- embassy-stm32-wpan/src/mac/mod.rs | 83 +---- embassy-stm32-wpan/src/mac/runner.rs | 329 +------------------ 6 files changed, 105 insertions(+), 1157 deletions(-) delete mode 100644 embassy-stm32-wpan/src/mac/ioctl.rs diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs index c67614dd..6e45e595 100644 --- a/embassy-stm32-wpan/src/mac/control.rs +++ b/embassy-stm32-wpan/src/mac/control.rs @@ -1,16 +1,4 @@ -use core::cmp::{max, min}; - -use ch::driver::LinkState; -use embassy_net_driver_channel as ch; -use embassy_time::{Duration, Timer}; - -pub use crate::bus::SpiBusCyw43; -use crate::consts::*; -use crate::events::{Event, EventSubscriber, Events}; -use crate::fmt::Bytes; -use crate::ioctl::{IoctlState, IoctlType}; -use crate::structs::*; -use crate::{countries, events, PowerManagementMode}; +use crate::mac::runner::Runner; #[derive(Debug)] pub struct Error { @@ -18,437 +6,15 @@ pub struct Error { } pub struct Control<'a> { - state_ch: ch::StateRunner<'a>, - events: &'a Events, - ioctl_state: &'a IoctlState, + runner: &'a Runner, } impl<'a> Control<'a> { - pub(crate) fn new(state_ch: ch::StateRunner<'a>, event_sub: &'a Events, ioctl_state: &'a IoctlState) -> Self { - Self { - state_ch, - events: event_sub, - ioctl_state, - } - } - - pub async fn init(&mut self, clm: &[u8]) { - const CHUNK_SIZE: usize = 1024; - - debug!("Downloading CLM..."); - - let mut offs = 0; - for chunk in clm.chunks(CHUNK_SIZE) { - let mut flag = DOWNLOAD_FLAG_HANDLER_VER; - if offs == 0 { - flag |= DOWNLOAD_FLAG_BEGIN; - } - offs += chunk.len(); - if offs == clm.len() { - flag |= DOWNLOAD_FLAG_END; - } - - let header = DownloadHeader { - flag, - dload_type: DOWNLOAD_TYPE_CLM, - len: chunk.len() as _, - crc: 0, - }; - let mut buf = [0; 8 + 12 + CHUNK_SIZE]; - buf[0..8].copy_from_slice(b"clmload\x00"); - buf[8..20].copy_from_slice(&header.to_bytes()); - buf[20..][..chunk.len()].copy_from_slice(&chunk); - self.ioctl(IoctlType::Set, IOCTL_CMD_SET_VAR, 0, &mut buf[..8 + 12 + chunk.len()]) - .await; + pub(crate) fn new(runner: &'a Runner) -> Self { + Self { runner: runner } } - // check clmload ok - assert_eq!(self.get_iovar_u32("clmload_status").await, 0); - - debug!("Configuring misc stuff..."); - - // Disable tx gloming which transfers multiple packets in one request. - // 'glom' is short for "conglomerate" which means "gather together into - // a compact mass". - self.set_iovar_u32("bus:txglom", 0).await; - self.set_iovar_u32("apsta", 1).await; - - // read MAC addr. - let mut mac_addr = [0; 6]; - assert_eq!(self.get_iovar("cur_etheraddr", &mut mac_addr).await, 6); - debug!("mac addr: {:02x}", Bytes(&mac_addr)); - - let country = countries::WORLD_WIDE_XX; - let country_info = CountryInfo { - country_abbrev: [country.code[0], country.code[1], 0, 0], - country_code: [country.code[0], country.code[1], 0, 0], - rev: if country.rev == 0 { -1 } else { country.rev as _ }, - }; - self.set_iovar("country", &country_info.to_bytes()).await; - - // set country takes some time, next ioctls fail if we don't wait. - Timer::after(Duration::from_millis(100)).await; - - // Set antenna to chip antenna - self.ioctl_set_u32(IOCTL_CMD_ANTDIV, 0, 0).await; - - self.set_iovar_u32("bus:txglom", 0).await; - Timer::after(Duration::from_millis(100)).await; - //self.set_iovar_u32("apsta", 1).await; // this crashes, also we already did it before...?? - //Timer::after(Duration::from_millis(100)).await; - self.set_iovar_u32("ampdu_ba_wsize", 8).await; - Timer::after(Duration::from_millis(100)).await; - self.set_iovar_u32("ampdu_mpdu", 4).await; - Timer::after(Duration::from_millis(100)).await; - //self.set_iovar_u32("ampdu_rx_factor", 0).await; // this crashes - - //Timer::after(Duration::from_millis(100)).await; - - // evts - let mut evts = EventMask { - iface: 0, - events: [0xFF; 24], - }; - - // Disable spammy uninteresting events. - evts.unset(Event::RADIO); - evts.unset(Event::IF); - evts.unset(Event::PROBREQ_MSG); - evts.unset(Event::PROBREQ_MSG_RX); - evts.unset(Event::PROBRESP_MSG); - evts.unset(Event::PROBRESP_MSG); - evts.unset(Event::ROAM); - - self.set_iovar("bsscfg:event_msgs", &evts.to_bytes()).await; - - Timer::after(Duration::from_millis(100)).await; - - // set wifi up - self.ioctl(IoctlType::Set, IOCTL_CMD_UP, 0, &mut []).await; - - Timer::after(Duration::from_millis(100)).await; - - self.ioctl_set_u32(110, 0, 1).await; // SET_GMODE = auto - self.ioctl_set_u32(142, 0, 0).await; // SET_BAND = any - - Timer::after(Duration::from_millis(100)).await; - - self.state_ch.set_ethernet_address(mac_addr); - - debug!("INIT DONE"); - } - - pub async fn set_power_management(&mut self, mode: PowerManagementMode) { - // power save mode - let mode_num = mode.mode(); - if mode_num == 2 { - self.set_iovar_u32("pm2_sleep_ret", mode.sleep_ret_ms() as u32).await; - self.set_iovar_u32("bcn_li_bcn", mode.beacon_period() as u32).await; - self.set_iovar_u32("bcn_li_dtim", mode.dtim_period() as u32).await; - self.set_iovar_u32("assoc_listen", mode.assoc() as u32).await; - } - self.ioctl_set_u32(86, 0, mode_num).await; - } - - pub async fn join_open(&mut self, ssid: &str) -> Result<(), Error> { - self.set_iovar_u32("ampdu_ba_wsize", 8).await; - - self.ioctl_set_u32(134, 0, 0).await; // wsec = open - self.set_iovar_u32x2("bsscfg:sup_wpa", 0, 0).await; - self.ioctl_set_u32(20, 0, 1).await; // set_infra = 1 - self.ioctl_set_u32(22, 0, 0).await; // set_auth = open (0) - - let mut i = SsidInfo { - len: ssid.len() as _, - ssid: [0; 32], - }; - i.ssid[..ssid.len()].copy_from_slice(ssid.as_bytes()); - - self.wait_for_join(i).await - } - - pub async fn join_wpa2(&mut self, ssid: &str, passphrase: &str) -> Result<(), Error> { - self.set_iovar_u32("ampdu_ba_wsize", 8).await; - - self.ioctl_set_u32(134, 0, 4).await; // wsec = wpa2 - self.set_iovar_u32x2("bsscfg:sup_wpa", 0, 1).await; - self.set_iovar_u32x2("bsscfg:sup_wpa2_eapver", 0, 0xFFFF_FFFF).await; - self.set_iovar_u32x2("bsscfg:sup_wpa_tmo", 0, 2500).await; - - Timer::after(Duration::from_millis(100)).await; - - let mut pfi = PassphraseInfo { - len: passphrase.len() as _, - flags: 1, - passphrase: [0; 64], - }; - pfi.passphrase[..passphrase.len()].copy_from_slice(passphrase.as_bytes()); - self.ioctl(IoctlType::Set, IOCTL_CMD_SET_PASSPHRASE, 0, &mut pfi.to_bytes()) - .await; // WLC_SET_WSEC_PMK - - self.ioctl_set_u32(20, 0, 1).await; // set_infra = 1 - self.ioctl_set_u32(22, 0, 0).await; // set_auth = 0 (open) - self.ioctl_set_u32(165, 0, 0x80).await; // set_wpa_auth - - let mut i = SsidInfo { - len: ssid.len() as _, - ssid: [0; 32], - }; - i.ssid[..ssid.len()].copy_from_slice(ssid.as_bytes()); - - self.wait_for_join(i).await - } - - async fn wait_for_join(&mut self, i: SsidInfo) -> Result<(), Error> { - self.events.mask.enable(&[Event::SET_SSID, Event::AUTH]); - let mut subscriber = self.events.queue.subscriber().unwrap(); - // the actual join operation starts here - // we make sure to enable events before so we don't miss any - - // set_ssid - self.ioctl(IoctlType::Set, IOCTL_CMD_SET_SSID, 0, &mut i.to_bytes()) - .await; - - // to complete the join, we wait for a SET_SSID event - // we also save the AUTH status for the user, it may be interesting - let mut auth_status = 0; - let status = loop { - let msg = subscriber.next_message_pure().await; - if msg.header.event_type == Event::AUTH && msg.header.status != EStatus::SUCCESS { - auth_status = msg.header.status; - } else if msg.header.event_type == Event::SET_SSID { - // join operation ends with SET_SSID event - break msg.header.status; - } - }; - - self.events.mask.disable_all(); - if status == EStatus::SUCCESS { - // successful join - self.state_ch.set_link_state(LinkState::Up); - debug!("JOINED"); - Ok(()) - } else { - warn!("JOIN failed with status={} auth={}", status, auth_status); - Err(Error { status }) - } - } - - pub async fn gpio_set(&mut self, gpio_n: u8, gpio_en: bool) { - assert!(gpio_n < 3); - self.set_iovar_u32x2("gpioout", 1 << gpio_n, if gpio_en { 1 << gpio_n } else { 0 }) - .await - } - - pub async fn start_ap_open(&mut self, ssid: &str, channel: u8) { - self.start_ap(ssid, "", Security::OPEN, channel).await; - } - - pub async fn start_ap_wpa2(&mut self, ssid: &str, passphrase: &str, channel: u8) { - self.start_ap(ssid, passphrase, Security::WPA2_AES_PSK, channel).await; - } - - async fn start_ap(&mut self, ssid: &str, passphrase: &str, security: Security, channel: u8) { - if security != Security::OPEN - && (passphrase.as_bytes().len() < MIN_PSK_LEN || passphrase.as_bytes().len() > MAX_PSK_LEN) - { - panic!("Passphrase is too short or too long"); - } - - // Temporarily set wifi down - self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).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; - - // Turn on AP mode - self.ioctl_set_u32(IOCTL_CMD_SET_AP, 0, 1).await; - - // Set SSID - let mut i = SsidInfoWithIndex { - index: 0, - ssid_info: SsidInfo { - len: ssid.as_bytes().len() as _, - ssid: [0; 32], - }, - }; - i.ssid_info.ssid[..ssid.as_bytes().len()].copy_from_slice(ssid.as_bytes()); - self.set_iovar("bsscfg:ssid", &i.to_bytes()).await; - - // Set channel number - self.ioctl_set_u32(IOCTL_CMD_SET_CHANNEL, 0, channel as u32).await; - - // Set security - self.set_iovar_u32x2("bsscfg:wsec", 0, (security as u32) & 0xFF).await; - - if security != Security::OPEN { - self.set_iovar_u32x2("bsscfg:wpa_auth", 0, 0x0084).await; // wpa_auth = WPA2_AUTH_PSK | WPA_AUTH_PSK - - Timer::after(Duration::from_millis(100)).await; - - // Set passphrase - let mut pfi = PassphraseInfo { - len: passphrase.as_bytes().len() as _, - flags: 1, // WSEC_PASSPHRASE - passphrase: [0; 64], - }; - pfi.passphrase[..passphrase.as_bytes().len()].copy_from_slice(passphrase.as_bytes()); - self.ioctl(IoctlType::Set, IOCTL_CMD_SET_PASSPHRASE, 0, &mut pfi.to_bytes()) - .await; - } - - // Change mutlicast rate from 1 Mbps to 11 Mbps - self.set_iovar_u32("2g_mrate", 11000000 / 500000).await; - - // Start AP - self.set_iovar_u32x2("bss", 0, 1).await; // bss = BSS_UP - } - - async fn set_iovar_u32x2(&mut self, name: &str, val1: u32, val2: u32) { - let mut buf = [0; 8]; - buf[0..4].copy_from_slice(&val1.to_le_bytes()); - buf[4..8].copy_from_slice(&val2.to_le_bytes()); - self.set_iovar(name, &buf).await - } - - async fn set_iovar_u32(&mut self, name: &str, val: u32) { - self.set_iovar(name, &val.to_le_bytes()).await - } - - async fn get_iovar_u32(&mut self, name: &str) -> u32 { - let mut buf = [0; 4]; - let len = self.get_iovar(name, &mut buf).await; - assert_eq!(len, 4); - u32::from_le_bytes(buf) - } - - async fn set_iovar(&mut self, name: &str, val: &[u8]) { - self.set_iovar_v::<64>(name, val).await - } - - async fn set_iovar_v(&mut self, name: &str, val: &[u8]) { - debug!("set {} = {:02x}", name, Bytes(val)); - - let mut buf = [0; BUFSIZE]; - buf[..name.len()].copy_from_slice(name.as_bytes()); - buf[name.len()] = 0; - buf[name.len() + 1..][..val.len()].copy_from_slice(val); - - let total_len = name.len() + 1 + val.len(); - self.ioctl(IoctlType::Set, IOCTL_CMD_SET_VAR, 0, &mut buf[..total_len]) - .await; - } - - // TODO this is not really working, it always returns all zeros. - async fn get_iovar(&mut self, name: &str, res: &mut [u8]) -> usize { - debug!("get {}", name); - - let mut buf = [0; 64]; - buf[..name.len()].copy_from_slice(name.as_bytes()); - buf[name.len()] = 0; - - let total_len = max(name.len() + 1, res.len()); - let res_len = self - .ioctl(IoctlType::Get, IOCTL_CMD_GET_VAR, 0, &mut buf[..total_len]) - .await; - - let out_len = min(res.len(), res_len); - res[..out_len].copy_from_slice(&buf[..out_len]); - out_len - } - - async fn ioctl_set_u32(&mut self, cmd: u32, iface: u32, val: u32) { - let mut buf = val.to_le_bytes(); - self.ioctl(IoctlType::Set, cmd, iface, &mut buf).await; - } - - async fn ioctl(&mut self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize { - struct CancelOnDrop<'a>(&'a IoctlState); - - impl CancelOnDrop<'_> { - fn defuse(self) { - core::mem::forget(self); - } - } - - impl Drop for CancelOnDrop<'_> { - fn drop(&mut self) { - self.0.cancel_ioctl(); - } - } - - let ioctl = CancelOnDrop(self.ioctl_state); - let resp_len = ioctl.0.do_ioctl(kind, cmd, iface, buf).await; - ioctl.defuse(); - - resp_len - } - - /// Start a wifi scan - /// - /// Returns a `Stream` of networks found by the device - /// - /// # Note - /// Device events are currently implemented using a bounded queue. - /// To not miss any events, you should make sure to always await the stream. - pub async fn scan(&mut self) -> Scanner<'_> { - const SCANTYPE_PASSIVE: u8 = 1; - - let scan_params = ScanParams { - version: 1, - action: 1, - sync_id: 1, - ssid_len: 0, - ssid: [0; 32], - bssid: [0xff; 6], - bss_type: 2, - scan_type: SCANTYPE_PASSIVE, - nprobes: !0, - active_time: !0, - passive_time: !0, - home_time: !0, - channel_num: 0, - channel_list: [0; 1], - }; - - self.events.mask.enable(&[Event::ESCAN_RESULT]); - let subscriber = self.events.queue.subscriber().unwrap(); - self.set_iovar_v::<256>("escan", &scan_params.to_bytes()).await; - - Scanner { - subscriber, - events: &self.events, - } - } -} - -pub struct Scanner<'a> { - subscriber: EventSubscriber<'a>, - events: &'a Events, -} - -impl Scanner<'_> { - /// wait for the next found network - pub async fn next(&mut self) -> Option { - let event = self.subscriber.next_message_pure().await; - if event.header.status != EStatus::PARTIAL { - self.events.mask.disable_all(); - return None; - } - - if let events::Payload::BssInfo(bss) = event.payload { - Some(bss) - } else { - None - } - } -} - -impl Drop for Scanner<'_> { - fn drop(&mut self) { - self.events.mask.disable_all(); + pub async fn init(&mut self) { + // TODO } } diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs index 3171d61f..00072749 100644 --- a/embassy-stm32-wpan/src/mac/driver.rs +++ b/embassy-stm32-wpan/src/mac/driver.rs @@ -1,102 +1,110 @@ -#![no_std] -#![no_main] #![allow(incomplete_features)] -#![feature(async_fn_in_trait, type_alias_impl_trait, concat_bytes)] #![deny(unused_must_use)] -use core::slice; +use core::task::Context; -use embassy_net_driver_channel as ch; -use embedded_hal_1::digital::OutputPin; -use events::Events; -use ioctl::IoctlState; +use embassy_net_driver::{Capabilities, LinkState, Medium}; -use crate::bus::Bus; -pub use crate::bus::SpiBusCyw43; -pub use crate::control::{Control, Error as ControlError}; -pub use crate::runner::Runner; -pub use crate::structs::BssInfo; +use crate::mac::runner::Runner; +use crate::mac::MTU; -const MTU: usize = 1514; - -pub struct State { - ioctl_state: IoctlState, - ch: ch::State, - events: Events, +pub struct Driver<'d> { + runner: &'d Runner, } -impl State { - pub fn new() -> Self { - Self { - ioctl_state: IoctlState::new(), - ch: ch::State::new(), - events: Events::new(), - } +impl<'d> Driver<'d> { + pub(crate) fn new(runner: &'d Runner) -> Self { + Self { runner: runner } } } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum PowerManagementMode { - /// Custom, officially unsupported mode. Use at your own risk. - /// All power-saving features set to their max at only a marginal decrease in power consumption - /// as oppposed to `Aggressive`. - SuperSave, +impl<'d> embassy_net_driver::Driver for Driver<'d> { + // type RxToken<'a> = RxToken<'a, 'd> where Self: 'a; + // type TxToken<'a> = TxToken<'a, 'd> where Self: 'a; + type RxToken<'a> = RxToken where Self: 'a; + type TxToken<'a> = TxToken where Self: 'a; - /// Aggressive power saving mode. - Aggressive, + fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { + // WAKER.register(cx.waker()); + // if self.rx.available().is_some() && self.tx.available().is_some() { + // Some((RxToken { rx: &mut self.rx }, TxToken { tx: &mut self.tx })) + // } else { + // None + // } - /// The default mode. - PowerSave, + None + } - /// Performance is prefered over power consumption but still some power is conserved as opposed to - /// `None`. - Performance, + fn transmit(&mut self, cx: &mut Context) -> Option> { + // WAKER.register(cx.waker()); + // / if self.tx.available().is_some() { + // / Some(TxToken { tx: &mut self.tx }) + // / } else { + // / None + // / } - /// Unlike all the other PM modes, this lowers the power consumption at all times at the cost of - /// a much lower throughput. - ThroughputThrottling, + None + } - /// No power management is configured. This consumes the most power. - None, -} + fn capabilities(&self) -> Capabilities { + let mut caps = Capabilities::default(); + caps.max_transmission_unit = MTU; + // caps.max_burst_size = Some(self.tx.len()); -impl Default for PowerManagementMode { - fn default() -> Self { - Self::PowerSave + caps.medium = Medium::Ieee802154; + caps + } + + fn link_state(&mut self, cx: &mut Context) -> LinkState { + // if self.phy.poll_link(&mut self.station_management, cx) { + // LinkState::Up + // } else { + // LinkState::Down + // } + + LinkState::Down + } + + fn ethernet_address(&self) -> [u8; 6] { + // self.mac_addr + + [0; 6] } } -impl PowerManagementMode { - // TODO +pub struct RxToken { + // rx: &'a mut RDesRing<'d>, } -pub type NetDriver<'a> = ch::Device<'a, MTU>; +impl embassy_net_driver::RxToken for RxToken { + fn consume(self, f: F) -> R + where + F: FnOnce(&mut [u8]) -> R, + { + // NOTE(unwrap): we checked the queue wasn't full when creating the token. + // let pkt = unwrap!(self.rx.available()); -pub async fn new<'a, PWR, SPI>( - state: &'a mut State, - pwr: PWR, - spi: SPI, - firmware: &[u8], -) -> (NetDriver<'a>, Control<'a>, Runner<'a, PWR, SPI>) -where - PWR: OutputPin, - SPI: SpiBusCyw43, -{ - let (ch_runner, device) = ch::new(&mut state.ch, [0; 6]); - let state_ch = ch_runner.state_runner(); - - let mut runner = Runner::new(ch_runner, Bus::new(pwr, spi), &state.ioctl_state, &state.events); - - runner.init(firmware).await; - - ( - device, - Control::new(state_ch, &state.events, &state.ioctl_state), - runner, - ) + let pkt = &[]; + let r = f(&mut pkt[0..]); + // self.rx.pop_packet(); + r + } } -fn slice8_mut(x: &mut [u32]) -> &mut [u8] { - let len = x.len() * 4; - unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) } +pub struct TxToken { + // tx: &'a mut TDesRing<'d>, +} + +impl embassy_net_driver::TxToken for TxToken { + fn consume(self, len: usize, f: F) -> R + where + F: FnOnce(&mut [u8]) -> R, + { + // NOTE(unwrap): we checked the queue wasn't full when creating the token. + // let pkt = unwrap!(self.tx.available()); + let pkt = &[]; + let r = f(&mut pkt[..len]); + // self.tx.transmit(len); + r + } } diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs index 661c06ac..a2bb7922 100644 --- a/embassy-stm32-wpan/src/mac/event.rs +++ b/embassy-stm32-wpan/src/mac/event.rs @@ -1,9 +1,3 @@ -use core::cell::RefCell; - -use embassy_sync::blocking_mutex::raw::NoopRawMutex; -use embassy_sync::pubsub::{PubSubChannel, Subscriber}; - -use super::helpers::to_u16; use core::mem; use super::indications::{ @@ -80,7 +74,6 @@ impl Event { } } -#[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum MacEvent<'a> { MlmeAssociateCnf(&'a AssociateConfirm), @@ -109,116 +102,3 @@ pub enum MacEvent<'a> { McpsDataInd(&'a DataIndication), MlmePollInd(&'a PollIndication), } - -// TODO this PubSub can probably be replaced with shared memory to make it a bit more efficient. -pub type EventQueue = PubSubChannel; -pub type EventSubscriber<'a> = Subscriber<'a, NoopRawMutex, Message, 2, 1, 1>; - -pub struct Events { - pub queue: EventQueue, - pub mask: SharedEventMask, -} - -impl Events { - pub fn new() -> Self { - Self { - queue: EventQueue::new(), - mask: SharedEventMask::default(), - } - } -} - -#[derive(Clone)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub struct Status { - pub event_type: MacEvent, - pub status: u32, -} - -#[derive(Clone, Copy)] -pub enum Payload { - None, - // BssInfo(BssInfo), -} - -#[derive(Clone)] - -pub struct Message { - pub header: Status, - pub payload: Payload, -} - -impl Message { - pub fn new(status: Status, payload: Payload) -> Self { - Self { - header: status, - payload, - } - } -} - -#[derive(Default)] -struct EventMask { - mask: [u32; Self::WORD_COUNT], -} - -impl EventMask { - const WORD_COUNT: usize = ((Event::LAST as u32 + (u32::BITS - 1)) / u32::BITS) as usize; - - fn enable(&mut self, event: MacEvent) { - let n = event as u32; - let word = n / u32::BITS; - let bit = n % u32::BITS; - - self.mask[word as usize] |= 1 << bit; - } - - fn disable(&mut self, event: MacEvent) { - let n = event as u32; - let word = n / u32::BITS; - let bit = n % u32::BITS; - - self.mask[word as usize] &= !(1 << bit); - } - - fn is_enabled(&self, event: MacEvent) -> bool { - let n = event as u32; - let word = n / u32::BITS; - let bit = n % u32::BITS; - - self.mask[word as usize] & (1 << bit) > 0 - } -} - -#[derive(Default)] - -pub struct SharedEventMask { - mask: RefCell, -} - -impl SharedEventMask { - pub fn enable(&self, events: &[MacEvent]) { - let mut mask = self.mask.borrow_mut(); - for event in events { - mask.enable(*event); - } - } - - #[allow(dead_code)] - pub fn disable(&self, events: &[MacEvent]) { - let mut mask = self.mask.borrow_mut(); - for event in events { - mask.disable(*event); - } - } - - pub fn disable_all(&self) { - let mut mask = self.mask.borrow_mut(); - mask.mask = Default::default(); - } - - pub fn is_enabled(&self, event: MacEvent) -> bool { - let mask = self.mask.borrow(); - mask.is_enabled(event) - } -} diff --git a/embassy-stm32-wpan/src/mac/ioctl.rs b/embassy-stm32-wpan/src/mac/ioctl.rs deleted file mode 100644 index 0fe55cd6..00000000 --- a/embassy-stm32-wpan/src/mac/ioctl.rs +++ /dev/null @@ -1,124 +0,0 @@ -use core::cell::{Cell, RefCell}; -use core::future::poll_fn; -use core::task::{Poll, Waker}; - -use embassy_sync::waitqueue::WakerRegistration; - -#[derive(Clone, Copy)] -pub enum IoctlType { - Get = 0, - Set = 2, -} - -#[derive(Clone, Copy)] -pub struct PendingIoctl { - pub buf: *mut [u8], - pub kind: IoctlType, - pub cmd: u32, - pub iface: u32, -} - -#[derive(Clone, Copy)] -enum IoctlStateInner { - Pending(PendingIoctl), - Sent { buf: *mut [u8] }, - Done { resp_len: usize }, -} - -struct Wakers { - control: WakerRegistration, - runner: WakerRegistration, -} - -impl Default for Wakers { - fn default() -> Self { - Self { - control: WakerRegistration::new(), - runner: WakerRegistration::new(), - } - } -} - -pub struct IoctlState { - state: Cell, - wakers: RefCell, -} - -impl IoctlState { - pub fn new() -> Self { - Self { - state: Cell::new(IoctlStateInner::Done { resp_len: 0 }), - wakers: Default::default(), - } - } - - fn wake_control(&self) { - self.wakers.borrow_mut().control.wake(); - } - - fn register_control(&self, waker: &Waker) { - self.wakers.borrow_mut().control.register(waker); - } - - fn wake_runner(&self) { - self.wakers.borrow_mut().runner.wake(); - } - - fn register_runner(&self, waker: &Waker) { - self.wakers.borrow_mut().runner.register(waker); - } - - pub async fn wait_complete(&self) -> usize { - poll_fn(|cx| { - if let IoctlStateInner::Done { resp_len } = self.state.get() { - Poll::Ready(resp_len) - } else { - self.register_control(cx.waker()); - Poll::Pending - } - }) - .await - } - - pub async fn wait_pending(&self) -> PendingIoctl { - let pending = poll_fn(|cx| { - if let IoctlStateInner::Pending(pending) = self.state.get() { - Poll::Ready(pending) - } else { - self.register_runner(cx.waker()); - Poll::Pending - } - }) - .await; - - self.state.set(IoctlStateInner::Sent { buf: pending.buf }); - pending - } - - pub fn cancel_ioctl(&self) { - self.state.set(IoctlStateInner::Done { resp_len: 0 }); - } - - pub async fn do_ioctl(&self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize { - self.state - .set(IoctlStateInner::Pending(PendingIoctl { buf, kind, cmd, iface })); - self.wake_runner(); - self.wait_complete().await - } - - pub fn ioctl_done(&self, response: &[u8]) { - if let IoctlStateInner::Sent { buf } = self.state.get() { - // trace!("IOCTL Response: {:02x}", Bytes(response)); - - // TODO fix this - (unsafe { &mut *buf }[..response.len()]).copy_from_slice(response); - - self.state.set(IoctlStateInner::Done { - resp_len: response.len(), - }); - self.wake_control(); - } else { - warn!("IOCTL Response but no pending Ioctl"); - } - } -} diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs index df03e423..e024aeae 100644 --- a/embassy-stm32-wpan/src/mac/mod.rs +++ b/embassy-stm32-wpan/src/mac/mod.rs @@ -1,9 +1,9 @@ pub mod commands; mod consts; pub mod control; +mod driver; pub mod event; pub mod indications; -mod ioctl; mod macros; mod opcodes; pub mod responses; @@ -12,86 +12,19 @@ pub mod typedefs; use core::slice; -use embassy_net_driver_channel as ch; - pub use crate::mac::control::{Control, Error as ControlError}; -use crate::mac::event::Events; -use crate::mac::ioctl::IoctlState; +use crate::mac::driver::Driver; pub use crate::mac::runner::Runner; use crate::sub::mac::Mac; -const MTU: usize = 1514; +const MTU: usize = 127; -pub struct State { - ioctl_state: IoctlState, - ch: ch::State, - events: Events, -} +pub async fn new<'a>(mac: Mac) -> (Runner, Control<'a>, Driver<'a>) { + let runner = Runner::new(mac); + let control = Control::new(&runner); + let driver = Driver::new(&runner); -impl State { - pub fn new() -> Self { - Self { - ioctl_state: IoctlState::new(), - ch: ch::State::new(), - events: Events::new(), - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum PowerManagementMode { - /// Custom, officially unsupported mode. Use at your own risk. - /// All power-saving features set to their max at only a marginal decrease in power consumption - /// as oppposed to `Aggressive`. - SuperSave, - - /// Aggressive power saving mode. - Aggressive, - - /// The default mode. - PowerSave, - - /// Performance is prefered over power consumption but still some power is conserved as opposed to - /// `None`. - Performance, - - /// Unlike all the other PM modes, this lowers the power consumption at all times at the cost of - /// a much lower throughput. - ThroughputThrottling, - - /// No power management is configured. This consumes the most power. - None, -} - -impl Default for PowerManagementMode { - fn default() -> Self { - Self::PowerSave - } -} - -impl PowerManagementMode { - // TODO -} - -pub type NetDriver<'a> = ch::Device<'a, MTU>; - -pub async fn new<'a>( - state: &'a mut State, - mac_subsystem: Mac, - firmware: &[u8], -) -> (NetDriver<'a>, Control<'a>, Runner<'a>) { - let (ch_runner, device) = ch::new(&mut state.ch, [0; 6]); - let state_ch = ch_runner.state_runner(); - - let mut runner = Runner::new(ch_runner, mac_subsystem, &state.ioctl_state, &state.events); - - runner.init(firmware).await; - - ( - device, - Control::new(state_ch, &state.events, &state.ioctl_state), - runner, - ) + (runner, control, driver) } fn slice8_mut(x: &mut [u32]) -> &mut [u8] { diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index fbb7cb74..e97c9c8e 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -1,342 +1,27 @@ use embassy_futures::select::{select3, Either3}; -use embassy_net_driver_channel as ch; -use embassy_sync::pubsub::PubSubBehavior; -use crate::mac::event::Events; -use crate::mac::ioctl::{IoctlState, PendingIoctl}; use crate::mac::MTU; use crate::sub::mac::Mac; -pub struct Runner<'a> { - ch: ch::Runner<'a, MTU>, +pub struct Runner { mac: Mac, - - ioctl_state: &'a IoctlState, - ioctl_id: u16, - sdpcm_seq: u8, - sdpcm_seq_max: u8, - - events: &'a Events, + // TODO: tx_ring + // TODO: rx_buf } -impl<'a> Runner<'a> { - pub(crate) fn new(ch: ch::Runner<'a, MTU>, mac: Mac, ioctl_state: &'a IoctlState, events: &'a Events) -> Self { - Self { - ch, - mac, - ioctl_state, - ioctl_id: 0, - sdpcm_seq: 0, - sdpcm_seq_max: 1, - events, - } +impl Runner { + pub(crate) fn new(mac: Mac) -> Self { + Self { mac } } pub(crate) async fn init(&mut self, firmware: &[u8]) { - self.bus.init().await; - - #[cfg(feature = "firmware-logs")] - self.log_init().await; - debug!("wifi init done"); } pub async fn run(mut self) -> ! { let mut buf = [0; 512]; loop { - #[cfg(feature = "firmware-logs")] - self.log_read().await; - - if self.has_credit() { - let ioctl = self.ioctl_state.wait_pending(); - let tx = self.ch.tx_buf(); - let ev = self.bus.wait_for_event(); - - match select3(ioctl, tx, ev).await { - Either3::First(PendingIoctl { - buf: iobuf, - kind, - cmd, - iface, - }) => { - self.send_ioctl(kind, cmd, iface, unsafe { &*iobuf }).await; - self.check_status(&mut buf).await; - } - Either3::Second(packet) => { - trace!("tx pkt {:02x}", Bytes(&packet[..packet.len().min(48)])); - - let mut buf = [0; 512]; - let buf8 = slice8_mut(&mut buf); - - // There MUST be 2 bytes of padding between the SDPCM and BDC headers. - // And ONLY for data packets! - // No idea why, but the firmware will append two zero bytes to the tx'd packets - // otherwise. If the packet is exactly 1514 bytes (the max MTU), this makes it - // be oversized and get dropped. - // WHD adds it here https://github.com/Infineon/wifi-host-driver/blob/c04fcbb6b0d049304f376cf483fd7b1b570c8cd5/WiFi_Host_Driver/src/include/whd_sdpcm.h#L90 - // and adds it to the header size her https://github.com/Infineon/wifi-host-driver/blob/c04fcbb6b0d049304f376cf483fd7b1b570c8cd5/WiFi_Host_Driver/src/whd_sdpcm.c#L597 - // ¯\_(ツ)_/¯ - const PADDING_SIZE: usize = 2; - let total_len = SdpcmHeader::SIZE + PADDING_SIZE + BdcHeader::SIZE + packet.len(); - - let seq = self.sdpcm_seq; - self.sdpcm_seq = self.sdpcm_seq.wrapping_add(1); - - let sdpcm_header = SdpcmHeader { - len: total_len as u16, // TODO does this len need to be rounded up to u32? - len_inv: !total_len as u16, - sequence: seq, - channel_and_flags: CHANNEL_TYPE_DATA, - next_length: 0, - header_length: (SdpcmHeader::SIZE + PADDING_SIZE) as _, - wireless_flow_control: 0, - bus_data_credit: 0, - reserved: [0, 0], - }; - - let bdc_header = BdcHeader { - flags: BDC_VERSION << BDC_VERSION_SHIFT, - priority: 0, - flags2: 0, - data_offset: 0, - }; - trace!("tx {:?}", sdpcm_header); - trace!(" {:?}", bdc_header); - - buf8[0..SdpcmHeader::SIZE].copy_from_slice(&sdpcm_header.to_bytes()); - buf8[SdpcmHeader::SIZE + PADDING_SIZE..][..BdcHeader::SIZE] - .copy_from_slice(&bdc_header.to_bytes()); - buf8[SdpcmHeader::SIZE + PADDING_SIZE + BdcHeader::SIZE..][..packet.len()] - .copy_from_slice(packet); - - let total_len = (total_len + 3) & !3; // round up to 4byte - - trace!(" {:02x}", Bytes(&buf8[..total_len.min(48)])); - - self.bus.wlan_write(&buf[..(total_len / 4)]).await; - self.ch.tx_done(); - self.check_status(&mut buf).await; - } - Either3::Third(()) => { - self.handle_irq(&mut buf).await; - } - } - } else { - warn!("TX stalled"); - self.bus.wait_for_event().await; - self.handle_irq(&mut buf).await; - } + // TODO } } - - /// Wait for IRQ on F2 packet available - async fn handle_irq(&mut self, buf: &mut [u32; 512]) { - // Receive stuff - let irq = self.bus.read16(FUNC_BUS, REG_BUS_INTERRUPT).await; - trace!("irq{}", FormatInterrupt(irq)); - - if irq & IRQ_F2_PACKET_AVAILABLE != 0 { - self.check_status(buf).await; - } - - if irq & IRQ_DATA_UNAVAILABLE != 0 { - // TODO what should we do here? - warn!("IRQ DATA_UNAVAILABLE, clearing..."); - self.bus.write16(FUNC_BUS, REG_BUS_INTERRUPT, 1).await; - } - } - - /// Handle F2 events while status register is set - async fn check_status(&mut self, buf: &mut [u32; 512]) { - loop { - let status = self.bus.status(); - trace!("check status{}", FormatStatus(status)); - - if status & STATUS_F2_PKT_AVAILABLE != 0 { - let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT; - self.bus.wlan_read(buf, len).await; - trace!("rx {:02x}", Bytes(&slice8_mut(buf)[..(len as usize).min(48)])); - self.rx(&mut slice8_mut(buf)[..len as usize]); - } else { - break; - } - } - } - - fn rx(&mut self, packet: &mut [u8]) { - let Some((sdpcm_header, payload)) = SdpcmHeader::parse(packet) else { - return; - }; - - self.update_credit(&sdpcm_header); - - let channel = sdpcm_header.channel_and_flags & 0x0f; - - match channel { - CHANNEL_TYPE_CONTROL => { - let Some((cdc_header, response)) = CdcHeader::parse(payload) else { - return; - }; - trace!(" {:?}", cdc_header); - - if cdc_header.id == self.ioctl_id { - if cdc_header.status != 0 { - // TODO: propagate error instead - panic!("IOCTL error {}", cdc_header.status as i32); - } - - self.ioctl_state.ioctl_done(response); - } - } - CHANNEL_TYPE_EVENT => { - let Some((_, bdc_packet)) = BdcHeader::parse(payload) else { - warn!("BDC event, incomplete header"); - return; - }; - - let Some((event_packet, evt_data)) = EventPacket::parse(bdc_packet) else { - warn!("BDC event, incomplete data"); - return; - }; - - const ETH_P_LINK_CTL: u16 = 0x886c; // HPNA, wlan link local tunnel, according to linux if_ether.h - if event_packet.eth.ether_type != ETH_P_LINK_CTL { - warn!( - "unexpected ethernet type 0x{:04x}, expected Broadcom ether type 0x{:04x}", - event_packet.eth.ether_type, ETH_P_LINK_CTL - ); - return; - } - const BROADCOM_OUI: &[u8] = &[0x00, 0x10, 0x18]; - if event_packet.hdr.oui != BROADCOM_OUI { - warn!( - "unexpected ethernet OUI {:02x}, expected Broadcom OUI {:02x}", - Bytes(&event_packet.hdr.oui), - Bytes(BROADCOM_OUI) - ); - return; - } - const BCMILCP_SUBTYPE_VENDOR_LONG: u16 = 32769; - if event_packet.hdr.subtype != BCMILCP_SUBTYPE_VENDOR_LONG { - warn!("unexpected subtype {}", event_packet.hdr.subtype); - return; - } - - const BCMILCP_BCM_SUBTYPE_EVENT: u16 = 1; - if event_packet.hdr.user_subtype != BCMILCP_BCM_SUBTYPE_EVENT { - warn!("unexpected user_subtype {}", event_packet.hdr.subtype); - return; - } - - let evt_type = events::Event::from(event_packet.msg.event_type as u8); - debug!( - "=== EVENT {:?}: {:?} {:02x}", - evt_type, - event_packet.msg, - Bytes(evt_data) - ); - - if self.events.mask.is_enabled(evt_type) { - let status = event_packet.msg.status; - let event_payload = match evt_type { - Event::ESCAN_RESULT if status == EStatus::PARTIAL => { - let Some((_, bss_info)) = ScanResults::parse(evt_data) else { - return; - }; - let Some(bss_info) = BssInfo::parse(bss_info) else { - return; - }; - events::Payload::BssInfo(*bss_info) - } - Event::ESCAN_RESULT => events::Payload::None, - _ => events::Payload::None, - }; - - // this intentionally uses the non-blocking publish immediate - // publish() is a deadlock risk in the current design as awaiting here prevents ioctls - // The `Runner` always yields when accessing the device, so consumers always have a chance to receive the event - // (if they are actively awaiting the queue) - self.events.queue.publish_immediate(events::Message::new( - Status { - event_type: evt_type, - status, - }, - event_payload, - )); - } - } - CHANNEL_TYPE_DATA => { - let Some((_, packet)) = BdcHeader::parse(payload) else { - return; - }; - trace!("rx pkt {:02x}", Bytes(&packet[..packet.len().min(48)])); - - match self.ch.try_rx_buf() { - Some(buf) => { - buf[..packet.len()].copy_from_slice(packet); - self.ch.rx_done(packet.len()) - } - None => warn!("failed to push rxd packet to the channel."), - } - } - _ => {} - } - } - - fn update_credit(&mut self, sdpcm_header: &SdpcmHeader) { - if sdpcm_header.channel_and_flags & 0xf < 3 { - let mut sdpcm_seq_max = sdpcm_header.bus_data_credit; - if sdpcm_seq_max.wrapping_sub(self.sdpcm_seq) > 0x40 { - sdpcm_seq_max = self.sdpcm_seq + 2; - } - self.sdpcm_seq_max = sdpcm_seq_max; - } - } - - fn has_credit(&self) -> bool { - self.sdpcm_seq != self.sdpcm_seq_max && self.sdpcm_seq_max.wrapping_sub(self.sdpcm_seq) & 0x80 == 0 - } - - async fn send_ioctl(&mut self, kind: IoctlType, cmd: u32, iface: u32, data: &[u8]) { - let mut buf = [0; 512]; - let buf8 = slice8_mut(&mut buf); - - let total_len = SdpcmHeader::SIZE + CdcHeader::SIZE + data.len(); - - let sdpcm_seq = self.sdpcm_seq; - self.sdpcm_seq = self.sdpcm_seq.wrapping_add(1); - self.ioctl_id = self.ioctl_id.wrapping_add(1); - - let sdpcm_header = SdpcmHeader { - len: total_len as u16, // TODO does this len need to be rounded up to u32? - len_inv: !total_len as u16, - sequence: sdpcm_seq, - channel_and_flags: CHANNEL_TYPE_CONTROL, - next_length: 0, - header_length: SdpcmHeader::SIZE as _, - wireless_flow_control: 0, - bus_data_credit: 0, - reserved: [0, 0], - }; - - let cdc_header = CdcHeader { - cmd: cmd, - len: data.len() as _, - flags: kind as u16 | (iface as u16) << 12, - id: self.ioctl_id, - status: 0, - }; - trace!("tx {:?}", sdpcm_header); - trace!(" {:?}", cdc_header); - - buf8[0..SdpcmHeader::SIZE].copy_from_slice(&sdpcm_header.to_bytes()); - buf8[SdpcmHeader::SIZE..][..CdcHeader::SIZE].copy_from_slice(&cdc_header.to_bytes()); - buf8[SdpcmHeader::SIZE + CdcHeader::SIZE..][..data.len()].copy_from_slice(data); - - let total_len = (total_len + 3) & !3; // round up to 4byte - - trace!(" {:02x}", Bytes(&buf8[..total_len.min(48)])); - - self.bus.wlan_write(&buf[..total_len / 4]).await; - } } From d040871f7a078db94846305463c30a461f821d7f Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 17 Jul 2023 20:14:06 -0500 Subject: [PATCH 119/148] wpan: fix comp errors and impl. some of runner --- embassy-stm32-wpan/src/mac/driver.rs | 8 +- embassy-stm32-wpan/src/mac/mod.rs | 9 +- embassy-stm32-wpan/src/mac/runner.rs | 75 ++++++++-- examples/stm32wb/src/bin/mac_ffd_net.rs | 180 ++++++++++++++++++++++++ 4 files changed, 255 insertions(+), 17 deletions(-) create mode 100644 examples/stm32wb/src/bin/mac_ffd_net.rs diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs index 00072749..118f6908 100644 --- a/embassy-stm32-wpan/src/mac/driver.rs +++ b/embassy-stm32-wpan/src/mac/driver.rs @@ -25,6 +25,8 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> { type TxToken<'a> = TxToken where Self: 'a; fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { + self.runner.rx_waker.register(cx.waker()); + // WAKER.register(cx.waker()); // if self.rx.available().is_some() && self.tx.available().is_some() { // Some((RxToken { rx: &mut self.rx }, TxToken { tx: &mut self.tx })) @@ -36,6 +38,8 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> { } fn transmit(&mut self, cx: &mut Context) -> Option> { + self.runner.tx_waker.register(cx.waker()); + // WAKER.register(cx.waker()); // / if self.tx.available().is_some() { // / Some(TxToken { tx: &mut self.tx }) @@ -84,7 +88,7 @@ impl embassy_net_driver::RxToken for RxToken { // NOTE(unwrap): we checked the queue wasn't full when creating the token. // let pkt = unwrap!(self.rx.available()); - let pkt = &[]; + let pkt = &mut []; let r = f(&mut pkt[0..]); // self.rx.pop_packet(); r @@ -102,7 +106,7 @@ impl embassy_net_driver::TxToken for TxToken { { // NOTE(unwrap): we checked the queue wasn't full when creating the token. // let pkt = unwrap!(self.tx.available()); - let pkt = &[]; + let pkt = &mut []; let r = f(&mut pkt[..len]); // self.tx.transmit(len); r diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs index e024aeae..2f9d1c81 100644 --- a/embassy-stm32-wpan/src/mac/mod.rs +++ b/embassy-stm32-wpan/src/mac/mod.rs @@ -15,16 +15,11 @@ use core::slice; pub use crate::mac::control::{Control, Error as ControlError}; use crate::mac::driver::Driver; pub use crate::mac::runner::Runner; -use crate::sub::mac::Mac; const MTU: usize = 127; -pub async fn new<'a>(mac: Mac) -> (Runner, Control<'a>, Driver<'a>) { - let runner = Runner::new(mac); - let control = Control::new(&runner); - let driver = Driver::new(&runner); - - (runner, control, driver) +pub async fn new<'a>(runner: &'a Runner) -> (Control<'a>, Driver<'a>) { + (Control::new(runner), Driver::new(runner)) } fn slice8_mut(x: &mut [u32]) -> &mut [u8] { diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index e97c9c8e..d545d6c9 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -1,27 +1,86 @@ use embassy_futures::select::{select3, Either3}; +use embassy_sync::waitqueue::AtomicWaker; +use crate::mac::event::{Event, MacEvent}; use crate::mac::MTU; use crate::sub::mac::Mac; +pub(crate) struct TxRing { + // stores n packets of up to mtu size + ring: [[u8; MTU]; 5], + pending: bool, + // start: u8, + // end: u8, +} + +impl TxRing { + pub(crate) fn new() -> Self { + Self { + ring: [[0; MTU]; 5], + pending: false, + } + } + + // wait for a free packet to become available + pub fn is_packet_free(&self) -> bool { + !self.pending + } + + // get the next available free packet + pub fn get_free_packet<'a>(&'a mut self) -> &'a mut [u8] { + self.pending = true; + + &mut self.ring[0] + } + + pub fn get_packet_to_transmit<'a>(&'a mut self) -> Option<&'a [u8]> { + if self.pending { + self.pending = false; + + Some(&self.ring[0]) + } else { + None + } + } +} + pub struct Runner { - mac: Mac, - // TODO: tx_ring - // TODO: rx_buf + mac_subsystem: Mac, + pub(crate) rx_ring: Option, + pub(crate) tx_ring: TxRing, + pub(crate) rx_waker: AtomicWaker, + pub(crate) tx_waker: AtomicWaker, } impl Runner { - pub(crate) fn new(mac: Mac) -> Self { - Self { mac } + pub fn new(mac: Mac) -> Self { + Self { + mac_subsystem: mac, + rx_ring: None, + tx_ring: TxRing::new(), + rx_waker: AtomicWaker::new(), + tx_waker: AtomicWaker::new(), + } } pub(crate) async fn init(&mut self, firmware: &[u8]) { debug!("wifi init done"); } - pub async fn run(mut self) -> ! { - let mut buf = [0; 512]; + pub async fn run(&self) -> ! { loop { - // TODO + let event = self.mac_subsystem.read().await; + if let Ok(evt) = event.mac_event() { + match evt { + MacEvent::McpsDataInd(data_ind) => { + // TODO: store mac_event in rx_ring + self.rx_waker.wake(); + } + _ => {} + } + } + + // TODO: select tx event } } } diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs new file mode 100644 index 00000000..b1cf051b --- /dev/null +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs @@ -0,0 +1,180 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::bind_interrupts; +use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32_wpan::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest}; +use embassy_stm32_wpan::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel}; +use embassy_stm32_wpan::mac::{self, Runner}; +use embassy_stm32_wpan::sub::mm; +use embassy_stm32_wpan::TlMbox; +use static_cell::make_static; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs{ + IPCC_C1_RX => ReceiveInterruptHandler; + IPCC_C1_TX => TransmitInterruptHandler; +}); + +#[embassy_executor::task] +async fn run_mm_queue(memory_manager: mm::MemoryManager) { + memory_manager.run_queue().await; +} + +#[embassy_executor::task] +async fn run_mac(runner: &'static Runner) { + runner.run().await; +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + /* + How to make this work: + + - Obtain a NUCLEO-STM32WB55 from your preferred supplier. + - Download and Install STM32CubeProgrammer. + - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from + gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x + - Open STM32CubeProgrammer + - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. + - Once complete, click connect to connect to the device. + - On the left hand pane, click the RSS signal icon to open "Firmware Upgrade Services". + - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file + - Select that file, the memory address, "verify download", and then "Firmware Upgrade". + - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the + stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. + - Select that file, the memory address, "verify download", and then "Firmware Upgrade". + - Select "Start Wireless Stack". + - Disconnect from the device. + - In the examples folder for stm32wb, modify the memory.x file to match your target device. + - Run this example. + + Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. + */ + + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + + let config = Config::default(); + let mbox = TlMbox::init(p.IPCC, Irqs, config); + + spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + + let sys_event = mbox.sys_subsystem.read().await; + info!("sys event: {}", sys_event.payload()); + + core::mem::drop(sys_event); + + let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; + info!("initialized mac: {}", result); + + info!("resetting"); + mbox.mac_subsystem + .send_command(&ResetRequest { + set_default_pib: true, + ..Default::default() + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + info!("setting extended address"); + let extended_address: u64 = 0xACDE480000000001; + mbox.mac_subsystem + .send_command(&SetRequest { + pib_attribute_ptr: &extended_address as *const _ as *const u8, + pib_attribute: PibId::ExtendedAddress, + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + info!("setting short address"); + let short_address: u16 = 0x1122; + mbox.mac_subsystem + .send_command(&SetRequest { + pib_attribute_ptr: &short_address as *const _ as *const u8, + pib_attribute: PibId::ShortAddress, + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + info!("setting association permit"); + let association_permit: bool = true; + mbox.mac_subsystem + .send_command(&SetRequest { + pib_attribute_ptr: &association_permit as *const _ as *const u8, + pib_attribute: PibId::AssociationPermit, + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + info!("setting TX power"); + let transmit_power: i8 = 2; + mbox.mac_subsystem + .send_command(&SetRequest { + pib_attribute_ptr: &transmit_power as *const _ as *const u8, + pib_attribute: PibId::TransmitPower, + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + info!("starting FFD device"); + mbox.mac_subsystem + .send_command(&StartRequest { + pan_id: PanId([0x1A, 0xAA]), + channel_number: MacChannel::Channel16, + beacon_order: 0x0F, + superframe_order: 0x0F, + pan_coordinator: true, + battery_life_extension: false, + ..Default::default() + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + info!("setting RX on when idle"); + let rx_on_while_idle: bool = true; + mbox.mac_subsystem + .send_command(&SetRequest { + pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, + pib_attribute: PibId::RxOnWhenIdle, + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + let runner = make_static!(Runner::new(mbox.mac_subsystem)); + + spawner.spawn(run_mac(runner)).unwrap(); + + let (driver, control) = mac::new(runner).await; +} From f581831b86f1f3e46a1cc7a8c4d1a2baf3379e6a Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Tue, 18 Jul 2023 10:39:29 +0200 Subject: [PATCH 120/148] Make dual-stack work in embassy-net --- embassy-net/src/lib.rs | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 0d0a986f..f43e3797 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -531,11 +531,14 @@ impl Inner { debug!(" IP address: {}", config.address); s.iface.update_ip_addrs(|addrs| { - if addrs.is_empty() { - addrs.push(IpCidr::Ipv4(config.address)).unwrap(); - } else { - addrs[0] = IpCidr::Ipv4(config.address); + 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-ethernet")] @@ -570,11 +573,14 @@ impl Inner { debug!(" IP address: {}", config.address); s.iface.update_ip_addrs(|addrs| { - if addrs.is_empty() { - addrs.push(IpCidr::Ipv6(config.address)).unwrap(); - } else { - addrs[0] = IpCidr::Ipv6(config.address); + 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")] @@ -643,12 +649,19 @@ impl Inner { } #[allow(unused)] // used only with dhcp - fn unapply_config(&mut self, s: &mut SocketStack) { + 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| ip_addrs.clear()); + s.iface.update_ip_addrs(|ip_addrs| { + if let Some((index, _)) = ip_addrs + .iter() + .enumerate() + .find(|(index, &addr)| matches!(addr, IpCidr::Ipv4(_))) + { + ip_addrs.remove(index); + } + }); #[cfg(feature = "medium-ethernet")] if medium == Medium::Ethernet { #[cfg(feature = "proto-ipv4")] @@ -695,7 +708,7 @@ impl Inner { if self.link_up { match socket.poll() { None => {} - Some(dhcpv4::Event::Deconfigured) => self.unapply_config(s), + Some(dhcpv4::Event::Deconfigured) => self.unapply_config_v4(s), Some(dhcpv4::Event::Configured(config)) => { let config = StaticConfigV4 { address: config.address, @@ -707,7 +720,7 @@ impl Inner { } } else if old_link_up { socket.reset(); - self.unapply_config(s); + self.unapply_config_v4(s); } } //if old_link_up || self.link_up { From 6bf4717b0a17cf4ca3439f0b2726b7fb6f5f3b13 Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Tue, 18 Jul 2023 10:57:05 +0200 Subject: [PATCH 121/148] cfg-gate `unapply_config_v4` --- embassy-net/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index f43e3797..ae595d0d 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -648,16 +648,17 @@ impl Inner { socket.set_retry_config(config.retry_config); } - #[allow(unused)] // used only with dhcp + #[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(|(index, &addr)| matches!(addr, IpCidr::Ipv4(_))) + .find(|(_, &addr)| matches!(addr, IpCidr::Ipv4(_))) { ip_addrs.remove(index); } From fc901f98564134368db3a92fb0644c5afe292f10 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 18 Jul 2023 13:54:41 +0200 Subject: [PATCH 122/148] ci: add check for no CRLF line endings. --- .github/ci/crlf.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 .github/ci/crlf.sh diff --git a/.github/ci/crlf.sh b/.github/ci/crlf.sh new file mode 100755 index 00000000..45751040 --- /dev/null +++ b/.github/ci/crlf.sh @@ -0,0 +1,17 @@ +#!/bin/bash +## on push branch~=gh-readonly-queue/main/.* +## on pull_request + +set -euo pipefail + +FILES_WITH_CRLF=$(find ! -path "./.git/*" -not -type d | xargs file -N | (grep " CRLF " || true)) + +if [ -z "$FILES_WITH_CRLF" ]; then + echo -e "No files with CRLF endings found." + exit 0 +else + NR_FILES=$(echo "$FILES_WITH_CRLF" | wc -l) + echo -e "ERROR: Found ${NR_FILES} files with CRLF endings." + echo "$FILES_WITH_CRLF" + exit "$NR_FILES" +fi \ No newline at end of file From 48957dce8767fb573527626b4a4a060fa3f1b98a Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 18 Jul 2023 14:14:25 +0200 Subject: [PATCH 123/148] Add gitattributes to control crlf conversion. --- .gitattributes | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..4db9edae --- /dev/null +++ b/.gitattributes @@ -0,0 +1,41 @@ +* text=auto + +*.adoc text +*.html text +*.in text +*.json text +*.md text +*.proto text +*.py text +*.rs text +*.service text +*.sh text +*.toml text +*.txt text +*.x text +*.yml text + +*.raw binary +*.bin binary +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.mov binary +*.mp4 binary +*.mp3 binary +*.flv binary +*.fla binary +*.swf binary +*.gz binary +*.zip binary +*.7z binary +*.ttf binary +*.eot binary +*.woff binary +*.pyc binary +*.pdf binary +*.ez binary +*.bz2 binary +*.swp binary \ No newline at end of file From 10f59667879bc476004c78bc0d3d6a0c4f560e55 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 18 Jul 2023 14:17:44 +0200 Subject: [PATCH 124/148] Convert files to LF endings. --- embassy-nrf/src/pdm.rs | 588 +++++++++++++++--------------- embassy-stm32/src/qspi/mod.rs | 664 +++++++++++++++++----------------- 2 files changed, 626 insertions(+), 626 deletions(-) diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index 0e30f700..efa1fbcc 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -1,294 +1,294 @@ -//! Pulse Density Modulation (PDM) mirophone driver. - -#![macro_use] - -use core::marker::PhantomData; -use core::sync::atomic::{compiler_fence, Ordering}; -use core::task::Poll; - -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::{into_ref, PeripheralRef}; -use futures::future::poll_fn; - -use crate::chip::EASY_DMA_SIZE; -use crate::gpio::sealed::Pin; -use crate::gpio::{AnyPin, Pin as GpioPin}; -use crate::interrupt::typelevel::Interrupt; -use crate::{interrupt, Peripheral}; - -/// Interrupt handler. -pub struct InterruptHandler { - _phantom: PhantomData, -} - -impl interrupt::typelevel::Handler for InterruptHandler { - unsafe fn on_interrupt() { - T::regs().intenclr.write(|w| w.end().clear()); - T::state().waker.wake(); - } -} - -/// PDM microphone interface -pub struct Pdm<'d, T: Instance> { - _peri: PeripheralRef<'d, T>, -} - -/// PDM error. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[non_exhaustive] -pub enum Error { - /// Buffer is too long. - BufferTooLong, - /// Buffer is empty - BufferZeroLength, - /// PDM is not running - NotRunning, -} - -static DUMMY_BUFFER: [i16; 1] = [0; 1]; - -impl<'d, T: Instance> Pdm<'d, T> { - /// Create PDM driver - pub fn new( - pdm: impl Peripheral

+ 'd, - _irq: impl interrupt::typelevel::Binding> + 'd, - clk: impl Peripheral

+ 'd, - din: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(pdm, clk, din); - Self::new_inner(pdm, clk.map_into(), din.map_into(), config) - } - - fn new_inner( - pdm: PeripheralRef<'d, T>, - clk: PeripheralRef<'d, AnyPin>, - din: PeripheralRef<'d, AnyPin>, - config: Config, - ) -> Self { - into_ref!(pdm); - - let r = T::regs(); - - // setup gpio pins - din.conf().write(|w| w.input().set_bit()); - r.psel.din.write(|w| unsafe { w.bits(din.psel_bits()) }); - clk.set_low(); - clk.conf().write(|w| w.dir().output()); - r.psel.clk.write(|w| unsafe { w.bits(clk.psel_bits()) }); - - // configure - // use default for - // - gain right - // - gain left - // - clk - // - ratio - r.mode.write(|w| { - w.edge().bit(config.edge == Edge::LeftRising); - w.operation().bit(config.operation_mode == OperationMode::Mono); - w - }); - r.gainl.write(|w| w.gainl().default_gain()); - r.gainr.write(|w| w.gainr().default_gain()); - - // IRQ - T::Interrupt::unpend(); - unsafe { T::Interrupt::enable() }; - - r.enable.write(|w| w.enable().set_bit()); - - Self { _peri: pdm } - } - - /// Start sampling microphon data into a dummy buffer - /// Usefull to start the microphon and keep it active between recording samples - pub async fn start(&mut self) { - let r = T::regs(); - - // start dummy sampling because microphon needs some setup time - r.sample - .ptr - .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); - r.sample - .maxcnt - .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); - - r.tasks_start.write(|w| unsafe { w.bits(1) }); - } - - /// Stop sampling microphon data inta a dummy buffer - pub async fn stop(&mut self) { - let r = T::regs(); - r.tasks_stop.write(|w| unsafe { w.bits(1) }); - r.events_started.reset(); - } - - /// Sample data into the given buffer. - pub async fn sample(&mut self, buffer: &mut [i16]) -> Result<(), Error> { - if buffer.len() == 0 { - return Err(Error::BufferZeroLength); - } - if buffer.len() > EASY_DMA_SIZE { - return Err(Error::BufferTooLong); - } - - let r = T::regs(); - - if r.events_started.read().bits() == 0 { - return Err(Error::NotRunning); - } - - let drop = OnDrop::new(move || { - r.intenclr.write(|w| w.end().clear()); - r.events_stopped.reset(); - - // reset to dummy buffer - r.sample - .ptr - .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); - r.sample - .maxcnt - .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); - - while r.events_stopped.read().bits() == 0 {} - }); - - // setup user buffer - let ptr = buffer.as_ptr(); - let len = buffer.len(); - r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(ptr as u32) }); - r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(len as _) }); - - // wait till the current sample is finished and the user buffer sample is started - Self::wait_for_sample().await; - - // reset the buffer back to the dummy buffer - r.sample - .ptr - .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); - r.sample - .maxcnt - .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); - - // wait till the user buffer is sampled - Self::wait_for_sample().await; - - drop.defuse(); - - Ok(()) - } - - async fn wait_for_sample() { - let r = T::regs(); - - r.events_end.reset(); - r.intenset.write(|w| w.end().set()); - - compiler_fence(Ordering::SeqCst); - - poll_fn(|cx| { - T::state().waker.register(cx.waker()); - if r.events_end.read().bits() != 0 { - return Poll::Ready(()); - } - Poll::Pending - }) - .await; - - compiler_fence(Ordering::SeqCst); - } -} - -/// PDM microphone driver Config -pub struct Config { - /// Use stero or mono operation - pub operation_mode: OperationMode, - /// On which edge the left channel should be samples - pub edge: Edge, -} - -impl Default for Config { - fn default() -> Self { - Self { - operation_mode: OperationMode::Mono, - edge: Edge::LeftFalling, - } - } -} - -/// PDM operation mode. -#[derive(PartialEq)] -pub enum OperationMode { - /// Mono (1 channel) - Mono, - /// Stereo (2 channels) - Stereo, -} - -/// PDM edge polarity -#[derive(PartialEq)] -pub enum Edge { - /// Left edge is rising - LeftRising, - /// Left edge is falling - LeftFalling, -} - -impl<'d, T: Instance> Drop for Pdm<'d, T> { - fn drop(&mut self) { - let r = T::regs(); - - r.tasks_stop.write(|w| unsafe { w.bits(1) }); - - r.enable.write(|w| w.enable().disabled()); - - r.psel.din.reset(); - r.psel.clk.reset(); - } -} - -pub(crate) mod sealed { - use embassy_sync::waitqueue::AtomicWaker; - - /// Peripheral static state - pub struct State { - pub waker: AtomicWaker, - } - - impl State { - pub const fn new() -> Self { - Self { - waker: AtomicWaker::new(), - } - } - } - - pub trait Instance { - fn regs() -> &'static crate::pac::pdm::RegisterBlock; - fn state() -> &'static State; - } -} - -/// PDM peripheral instance. -pub trait Instance: Peripheral

+ sealed::Instance + 'static + Send { - /// Interrupt for this peripheral. - type Interrupt: interrupt::typelevel::Interrupt; -} - -macro_rules! impl_pdm { - ($type:ident, $pac_type:ident, $irq:ident) => { - impl crate::pdm::sealed::Instance for peripherals::$type { - fn regs() -> &'static crate::pac::pdm::RegisterBlock { - unsafe { &*pac::$pac_type::ptr() } - } - fn state() -> &'static crate::pdm::sealed::State { - static STATE: crate::pdm::sealed::State = crate::pdm::sealed::State::new(); - &STATE - } - } - impl crate::pdm::Instance for peripherals::$type { - type Interrupt = crate::interrupt::typelevel::$irq; - } - }; -} +//! Pulse Density Modulation (PDM) mirophone driver. + +#![macro_use] + +use core::marker::PhantomData; +use core::sync::atomic::{compiler_fence, Ordering}; +use core::task::Poll; + +use embassy_hal_common::drop::OnDrop; +use embassy_hal_common::{into_ref, PeripheralRef}; +use futures::future::poll_fn; + +use crate::chip::EASY_DMA_SIZE; +use crate::gpio::sealed::Pin; +use crate::gpio::{AnyPin, Pin as GpioPin}; +use crate::interrupt::typelevel::Interrupt; +use crate::{interrupt, Peripheral}; + +/// Interrupt handler. +pub struct InterruptHandler { + _phantom: PhantomData, +} + +impl interrupt::typelevel::Handler for InterruptHandler { + unsafe fn on_interrupt() { + T::regs().intenclr.write(|w| w.end().clear()); + T::state().waker.wake(); + } +} + +/// PDM microphone interface +pub struct Pdm<'d, T: Instance> { + _peri: PeripheralRef<'d, T>, +} + +/// PDM error. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum Error { + /// Buffer is too long. + BufferTooLong, + /// Buffer is empty + BufferZeroLength, + /// PDM is not running + NotRunning, +} + +static DUMMY_BUFFER: [i16; 1] = [0; 1]; + +impl<'d, T: Instance> Pdm<'d, T> { + /// Create PDM driver + pub fn new( + pdm: impl Peripheral

+ 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, + clk: impl Peripheral

+ 'd, + din: impl Peripheral

+ 'd, + config: Config, + ) -> Self { + into_ref!(pdm, clk, din); + Self::new_inner(pdm, clk.map_into(), din.map_into(), config) + } + + fn new_inner( + pdm: PeripheralRef<'d, T>, + clk: PeripheralRef<'d, AnyPin>, + din: PeripheralRef<'d, AnyPin>, + config: Config, + ) -> Self { + into_ref!(pdm); + + let r = T::regs(); + + // setup gpio pins + din.conf().write(|w| w.input().set_bit()); + r.psel.din.write(|w| unsafe { w.bits(din.psel_bits()) }); + clk.set_low(); + clk.conf().write(|w| w.dir().output()); + r.psel.clk.write(|w| unsafe { w.bits(clk.psel_bits()) }); + + // configure + // use default for + // - gain right + // - gain left + // - clk + // - ratio + r.mode.write(|w| { + w.edge().bit(config.edge == Edge::LeftRising); + w.operation().bit(config.operation_mode == OperationMode::Mono); + w + }); + r.gainl.write(|w| w.gainl().default_gain()); + r.gainr.write(|w| w.gainr().default_gain()); + + // IRQ + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; + + r.enable.write(|w| w.enable().set_bit()); + + Self { _peri: pdm } + } + + /// Start sampling microphon data into a dummy buffer + /// Usefull to start the microphon and keep it active between recording samples + pub async fn start(&mut self) { + let r = T::regs(); + + // start dummy sampling because microphon needs some setup time + r.sample + .ptr + .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); + r.sample + .maxcnt + .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); + + r.tasks_start.write(|w| unsafe { w.bits(1) }); + } + + /// Stop sampling microphon data inta a dummy buffer + pub async fn stop(&mut self) { + let r = T::regs(); + r.tasks_stop.write(|w| unsafe { w.bits(1) }); + r.events_started.reset(); + } + + /// Sample data into the given buffer. + pub async fn sample(&mut self, buffer: &mut [i16]) -> Result<(), Error> { + if buffer.len() == 0 { + return Err(Error::BufferZeroLength); + } + if buffer.len() > EASY_DMA_SIZE { + return Err(Error::BufferTooLong); + } + + let r = T::regs(); + + if r.events_started.read().bits() == 0 { + return Err(Error::NotRunning); + } + + let drop = OnDrop::new(move || { + r.intenclr.write(|w| w.end().clear()); + r.events_stopped.reset(); + + // reset to dummy buffer + r.sample + .ptr + .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); + r.sample + .maxcnt + .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); + + while r.events_stopped.read().bits() == 0 {} + }); + + // setup user buffer + let ptr = buffer.as_ptr(); + let len = buffer.len(); + r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(ptr as u32) }); + r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(len as _) }); + + // wait till the current sample is finished and the user buffer sample is started + Self::wait_for_sample().await; + + // reset the buffer back to the dummy buffer + r.sample + .ptr + .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); + r.sample + .maxcnt + .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); + + // wait till the user buffer is sampled + Self::wait_for_sample().await; + + drop.defuse(); + + Ok(()) + } + + async fn wait_for_sample() { + let r = T::regs(); + + r.events_end.reset(); + r.intenset.write(|w| w.end().set()); + + compiler_fence(Ordering::SeqCst); + + poll_fn(|cx| { + T::state().waker.register(cx.waker()); + if r.events_end.read().bits() != 0 { + return Poll::Ready(()); + } + Poll::Pending + }) + .await; + + compiler_fence(Ordering::SeqCst); + } +} + +/// PDM microphone driver Config +pub struct Config { + /// Use stero or mono operation + pub operation_mode: OperationMode, + /// On which edge the left channel should be samples + pub edge: Edge, +} + +impl Default for Config { + fn default() -> Self { + Self { + operation_mode: OperationMode::Mono, + edge: Edge::LeftFalling, + } + } +} + +/// PDM operation mode. +#[derive(PartialEq)] +pub enum OperationMode { + /// Mono (1 channel) + Mono, + /// Stereo (2 channels) + Stereo, +} + +/// PDM edge polarity +#[derive(PartialEq)] +pub enum Edge { + /// Left edge is rising + LeftRising, + /// Left edge is falling + LeftFalling, +} + +impl<'d, T: Instance> Drop for Pdm<'d, T> { + fn drop(&mut self) { + let r = T::regs(); + + r.tasks_stop.write(|w| unsafe { w.bits(1) }); + + r.enable.write(|w| w.enable().disabled()); + + r.psel.din.reset(); + r.psel.clk.reset(); + } +} + +pub(crate) mod sealed { + use embassy_sync::waitqueue::AtomicWaker; + + /// Peripheral static state + pub struct State { + pub waker: AtomicWaker, + } + + impl State { + pub const fn new() -> Self { + Self { + waker: AtomicWaker::new(), + } + } + } + + pub trait Instance { + fn regs() -> &'static crate::pac::pdm::RegisterBlock; + fn state() -> &'static State; + } +} + +/// PDM peripheral instance. +pub trait Instance: Peripheral

+ sealed::Instance + 'static + Send { + /// Interrupt for this peripheral. + type Interrupt: interrupt::typelevel::Interrupt; +} + +macro_rules! impl_pdm { + ($type:ident, $pac_type:ident, $irq:ident) => { + impl crate::pdm::sealed::Instance for peripherals::$type { + fn regs() -> &'static crate::pac::pdm::RegisterBlock { + unsafe { &*pac::$pac_type::ptr() } + } + fn state() -> &'static crate::pdm::sealed::State { + static STATE: crate::pdm::sealed::State = crate::pdm::sealed::State::new(); + &STATE + } + } + impl crate::pdm::Instance for peripherals::$type { + type Interrupt = crate::interrupt::typelevel::$irq; + } + }; +} diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index e9db934b..31b67608 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -1,332 +1,332 @@ -#![macro_use] - -pub mod enums; - -use embassy_hal_common::{into_ref, PeripheralRef}; -use enums::*; - -use crate::dma::Transfer; -use crate::gpio::sealed::AFType; -use crate::gpio::AnyPin; -use crate::pac::quadspi::Quadspi as Regs; -use crate::rcc::RccPeripheral; -use crate::{peripherals, Peripheral}; - -pub struct TransferConfig { - /// Instraction width (IMODE) - pub iwidth: QspiWidth, - /// Address width (ADMODE) - pub awidth: QspiWidth, - /// Data width (DMODE) - pub dwidth: QspiWidth, - /// Instruction Id - pub instruction: u8, - /// Flash memory address - pub address: Option, - /// Number of dummy cycles (DCYC) - pub dummy: DummyCycles, - /// Length of data - pub data_len: Option, -} - -impl Default for TransferConfig { - fn default() -> Self { - Self { - iwidth: QspiWidth::NONE, - awidth: QspiWidth::NONE, - dwidth: QspiWidth::NONE, - instruction: 0, - address: None, - dummy: DummyCycles::_0, - data_len: None, - } - } -} - -pub struct Config { - /// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen. - /// If you need other value the whose predefined use `Other` variant. - pub memory_size: MemorySize, - /// Address size (8/16/24/32-bit) - pub address_size: AddressSize, - /// Scalar factor for generating CLK [0-255] - pub prescaler: u8, - /// Number of bytes to trigger FIFO threshold flag. - pub fifo_threshold: FIFOThresholdLevel, - /// Minimum number of cycles that chip select must be high between issued commands - pub cs_high_time: ChipSelectHightTime, -} - -impl Default for Config { - fn default() -> Self { - Self { - memory_size: MemorySize::Other(0), - address_size: AddressSize::_24bit, - prescaler: 128, - fifo_threshold: FIFOThresholdLevel::_17Bytes, - cs_high_time: ChipSelectHightTime::_5Cycle, - } - } -} - -#[allow(dead_code)] -pub struct Qspi<'d, T: Instance, Dma> { - _peri: PeripheralRef<'d, T>, - sck: Option>, - d0: Option>, - d1: Option>, - d2: Option>, - d3: Option>, - nss: Option>, - dma: PeripheralRef<'d, Dma>, - config: Config, -} - -impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { - pub fn new( - peri: impl Peripheral

+ 'd, - d0: impl Peripheral

> + 'd, - d1: impl Peripheral

> + 'd, - d2: impl Peripheral

> + 'd, - d3: impl Peripheral

> + 'd, - sck: impl Peripheral

> + 'd, - nss: impl Peripheral

> + 'd, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, d0, d1, d2, d3, sck, nss); - - sck.set_as_af(sck.af_num(), AFType::OutputPushPull); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af(nss.af_num(), AFType::OutputPushPull); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af(d0.af_num(), AFType::OutputPushPull); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af(d1.af_num(), AFType::OutputPushPull); - d1.set_speed(crate::gpio::Speed::VeryHigh); - d2.set_as_af(d2.af_num(), AFType::OutputPushPull); - d2.set_speed(crate::gpio::Speed::VeryHigh); - d3.set_as_af(d3.af_num(), AFType::OutputPushPull); - d3.set_speed(crate::gpio::Speed::VeryHigh); - - Self::new_inner( - peri, - Some(d0.map_into()), - Some(d1.map_into()), - Some(d2.map_into()), - Some(d3.map_into()), - Some(sck.map_into()), - Some(nss.map_into()), - dma, - config, - ) - } - - fn new_inner( - peri: impl Peripheral

+ 'd, - d0: Option>, - d1: Option>, - d2: Option>, - d3: Option>, - sck: Option>, - nss: Option>, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, dma); - - T::enable(); - T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); - - while T::REGS.sr().read().busy() {} - - T::REGS.cr().write(|w| { - w.set_prescaler(config.prescaler); - w.set_en(true); - }); - T::REGS.dcr().write(|w| { - w.set_fsize(config.memory_size.into()); - w.set_csht(config.cs_high_time.into()); - w.set_ckmode(false); - }); - - Self { - _peri: peri, - sck, - d0, - d1, - d2, - d3, - nss, - dma, - config, - } - } - - pub fn command(&mut self, transaction: TransferConfig) { - T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::IndirectWrite, &transaction); - - while !T::REGS.sr().read().tcf() {} - T::REGS.fcr().modify(|v| v.set_ctcf(true)); - } - - pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { - T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::IndirectWrite, &transaction); - - if let Some(len) = transaction.data_len { - let current_ar = T::REGS.ar().read().address(); - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectRead.into()); - }); - T::REGS.ar().write(|v| { - v.set_address(current_ar); - }); - - for idx in 0..len { - while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} - buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() }; - } - } - - while !T::REGS.sr().read().tcf() {} - T::REGS.fcr().modify(|v| v.set_ctcf(true)); - } - - pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { - T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::IndirectWrite, &transaction); - - if let Some(len) = transaction.data_len { - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectWrite.into()); - }); - - for idx in 0..len { - while !T::REGS.sr().read().ftf() {} - unsafe { (T::REGS.dr().as_ptr() as *mut u8).write_volatile(buf[idx]) }; - } - } - - while !T::REGS.sr().read().tcf() {} - T::REGS.fcr().modify(|v| v.set_ctcf(true)); - } - - pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) - where - Dma: QuadDma, - { - self.setup_transaction(QspiMode::IndirectWrite, &transaction); - - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectRead.into()); - }); - let current_ar = T::REGS.ar().read().address(); - T::REGS.ar().write(|v| { - v.set_address(current_ar); - }); - - let request = self.dma.request(); - let transfer = unsafe { - Transfer::new_read( - &mut self.dma, - request, - T::REGS.dr().as_ptr() as *mut u8, - buf, - Default::default(), - ) - }; - - T::REGS.cr().modify(|v| v.set_dmaen(true)); - - transfer.blocking_wait(); - } - - pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) - where - Dma: QuadDma, - { - self.setup_transaction(QspiMode::IndirectWrite, &transaction); - - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectWrite.into()); - }); - - let request = self.dma.request(); - let transfer = unsafe { - Transfer::new_write( - &mut self.dma, - request, - buf, - T::REGS.dr().as_ptr() as *mut u8, - Default::default(), - ) - }; - - T::REGS.cr().modify(|v| v.set_dmaen(true)); - - transfer.blocking_wait(); - } - - fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) { - T::REGS.fcr().modify(|v| { - v.set_csmf(true); - v.set_ctcf(true); - v.set_ctef(true); - v.set_ctof(true); - }); - - while T::REGS.sr().read().busy() {} - - if let Some(len) = transaction.data_len { - T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1)); - } - - T::REGS.ccr().write(|v| { - v.set_fmode(fmode.into()); - v.set_imode(transaction.iwidth.into()); - v.set_instruction(transaction.instruction); - v.set_admode(transaction.awidth.into()); - v.set_adsize(self.config.address_size.into()); - v.set_dmode(transaction.dwidth.into()); - v.set_abmode(QspiWidth::NONE.into()); - v.set_dcyc(transaction.dummy.into()); - }); - - if let Some(addr) = transaction.address { - T::REGS.ar().write(|v| { - v.set_address(addr); - }); - } - } -} - -pub(crate) mod sealed { - use super::*; - - pub trait Instance { - const REGS: Regs; - } -} - -pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} - -pin_trait!(SckPin, Instance); -pin_trait!(D0Pin, Instance); -pin_trait!(D1Pin, Instance); -pin_trait!(D2Pin, Instance); -pin_trait!(D3Pin, Instance); -pin_trait!(NSSPin, Instance); - -dma_trait!(QuadDma, Instance); - -foreach_peripheral!( - (quadspi, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { - const REGS: Regs = crate::pac::$inst; - } - - impl Instance for peripherals::$inst {} - }; -); +#![macro_use] + +pub mod enums; + +use embassy_hal_common::{into_ref, PeripheralRef}; +use enums::*; + +use crate::dma::Transfer; +use crate::gpio::sealed::AFType; +use crate::gpio::AnyPin; +use crate::pac::quadspi::Quadspi as Regs; +use crate::rcc::RccPeripheral; +use crate::{peripherals, Peripheral}; + +pub struct TransferConfig { + /// Instraction width (IMODE) + pub iwidth: QspiWidth, + /// Address width (ADMODE) + pub awidth: QspiWidth, + /// Data width (DMODE) + pub dwidth: QspiWidth, + /// Instruction Id + pub instruction: u8, + /// Flash memory address + pub address: Option, + /// Number of dummy cycles (DCYC) + pub dummy: DummyCycles, + /// Length of data + pub data_len: Option, +} + +impl Default for TransferConfig { + fn default() -> Self { + Self { + iwidth: QspiWidth::NONE, + awidth: QspiWidth::NONE, + dwidth: QspiWidth::NONE, + instruction: 0, + address: None, + dummy: DummyCycles::_0, + data_len: None, + } + } +} + +pub struct Config { + /// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen. + /// If you need other value the whose predefined use `Other` variant. + pub memory_size: MemorySize, + /// Address size (8/16/24/32-bit) + pub address_size: AddressSize, + /// Scalar factor for generating CLK [0-255] + pub prescaler: u8, + /// Number of bytes to trigger FIFO threshold flag. + pub fifo_threshold: FIFOThresholdLevel, + /// Minimum number of cycles that chip select must be high between issued commands + pub cs_high_time: ChipSelectHightTime, +} + +impl Default for Config { + fn default() -> Self { + Self { + memory_size: MemorySize::Other(0), + address_size: AddressSize::_24bit, + prescaler: 128, + fifo_threshold: FIFOThresholdLevel::_17Bytes, + cs_high_time: ChipSelectHightTime::_5Cycle, + } + } +} + +#[allow(dead_code)] +pub struct Qspi<'d, T: Instance, Dma> { + _peri: PeripheralRef<'d, T>, + sck: Option>, + d0: Option>, + d1: Option>, + d2: Option>, + d3: Option>, + nss: Option>, + dma: PeripheralRef<'d, Dma>, + config: Config, +} + +impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { + pub fn new( + peri: impl Peripheral

+ 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + sck: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

+ 'd, + config: Config, + ) -> Self { + into_ref!(peri, d0, d1, d2, d3, sck, nss); + + sck.set_as_af(sck.af_num(), AFType::OutputPushPull); + sck.set_speed(crate::gpio::Speed::VeryHigh); + nss.set_as_af(nss.af_num(), AFType::OutputPushPull); + nss.set_speed(crate::gpio::Speed::VeryHigh); + d0.set_as_af(d0.af_num(), AFType::OutputPushPull); + d0.set_speed(crate::gpio::Speed::VeryHigh); + d1.set_as_af(d1.af_num(), AFType::OutputPushPull); + d1.set_speed(crate::gpio::Speed::VeryHigh); + d2.set_as_af(d2.af_num(), AFType::OutputPushPull); + d2.set_speed(crate::gpio::Speed::VeryHigh); + d3.set_as_af(d3.af_num(), AFType::OutputPushPull); + d3.set_speed(crate::gpio::Speed::VeryHigh); + + Self::new_inner( + peri, + Some(d0.map_into()), + Some(d1.map_into()), + Some(d2.map_into()), + Some(d3.map_into()), + Some(sck.map_into()), + Some(nss.map_into()), + dma, + config, + ) + } + + fn new_inner( + peri: impl Peripheral

+ 'd, + d0: Option>, + d1: Option>, + d2: Option>, + d3: Option>, + sck: Option>, + nss: Option>, + dma: impl Peripheral

+ 'd, + config: Config, + ) -> Self { + into_ref!(peri, dma); + + T::enable(); + T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); + + while T::REGS.sr().read().busy() {} + + T::REGS.cr().write(|w| { + w.set_prescaler(config.prescaler); + w.set_en(true); + }); + T::REGS.dcr().write(|w| { + w.set_fsize(config.memory_size.into()); + w.set_csht(config.cs_high_time.into()); + w.set_ckmode(false); + }); + + Self { + _peri: peri, + sck, + d0, + d1, + d2, + d3, + nss, + dma, + config, + } + } + + pub fn command(&mut self, transaction: TransferConfig) { + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); + + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); + } + + pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); + + if let Some(len) = transaction.data_len { + let current_ar = T::REGS.ar().read().address(); + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectRead.into()); + }); + T::REGS.ar().write(|v| { + v.set_address(current_ar); + }); + + for idx in 0..len { + while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} + buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() }; + } + } + + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); + } + + pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); + + if let Some(len) = transaction.data_len { + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectWrite.into()); + }); + + for idx in 0..len { + while !T::REGS.sr().read().ftf() {} + unsafe { (T::REGS.dr().as_ptr() as *mut u8).write_volatile(buf[idx]) }; + } + } + + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); + } + + pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) + where + Dma: QuadDma, + { + self.setup_transaction(QspiMode::IndirectWrite, &transaction); + + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectRead.into()); + }); + let current_ar = T::REGS.ar().read().address(); + T::REGS.ar().write(|v| { + v.set_address(current_ar); + }); + + let request = self.dma.request(); + let transfer = unsafe { + Transfer::new_read( + &mut self.dma, + request, + T::REGS.dr().as_ptr() as *mut u8, + buf, + Default::default(), + ) + }; + + T::REGS.cr().modify(|v| v.set_dmaen(true)); + + transfer.blocking_wait(); + } + + pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) + where + Dma: QuadDma, + { + self.setup_transaction(QspiMode::IndirectWrite, &transaction); + + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectWrite.into()); + }); + + let request = self.dma.request(); + let transfer = unsafe { + Transfer::new_write( + &mut self.dma, + request, + buf, + T::REGS.dr().as_ptr() as *mut u8, + Default::default(), + ) + }; + + T::REGS.cr().modify(|v| v.set_dmaen(true)); + + transfer.blocking_wait(); + } + + fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) { + T::REGS.fcr().modify(|v| { + v.set_csmf(true); + v.set_ctcf(true); + v.set_ctef(true); + v.set_ctof(true); + }); + + while T::REGS.sr().read().busy() {} + + if let Some(len) = transaction.data_len { + T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1)); + } + + T::REGS.ccr().write(|v| { + v.set_fmode(fmode.into()); + v.set_imode(transaction.iwidth.into()); + v.set_instruction(transaction.instruction); + v.set_admode(transaction.awidth.into()); + v.set_adsize(self.config.address_size.into()); + v.set_dmode(transaction.dwidth.into()); + v.set_abmode(QspiWidth::NONE.into()); + v.set_dcyc(transaction.dummy.into()); + }); + + if let Some(addr) = transaction.address { + T::REGS.ar().write(|v| { + v.set_address(addr); + }); + } + } +} + +pub(crate) mod sealed { + use super::*; + + pub trait Instance { + const REGS: Regs; + } +} + +pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} + +pin_trait!(SckPin, Instance); +pin_trait!(D0Pin, Instance); +pin_trait!(D1Pin, Instance); +pin_trait!(D2Pin, Instance); +pin_trait!(D3Pin, Instance); +pin_trait!(NSSPin, Instance); + +dma_trait!(QuadDma, Instance); + +foreach_peripheral!( + (quadspi, $inst:ident) => { + impl sealed::Instance for peripherals::$inst { + const REGS: Regs = crate::pac::$inst; + } + + impl Instance for peripherals::$inst {} + }; +); From 98576c17b6c29972074867499332365f7f3e89db Mon Sep 17 00:00:00 2001 From: ivmarkov Date: Tue, 18 Jul 2023 18:35:20 +0300 Subject: [PATCH 125/148] Fix multicast support (#1670) --- embassy-net/src/lib.rs | 62 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index ae595d0d..4fbafe75 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -479,30 +479,78 @@ impl Stack { } #[cfg(feature = "igmp")] -impl Stack { +impl Stack { /// Join a multicast group. - pub fn join_multicast_group(&self, addr: T) -> Result + pub async fn join_multicast_group(&self, addr: T) -> Result + where + T: Into, + { + let addr = addr.into(); + + poll_fn(move |cx| self.poll_join_multicast_group(addr, cx)).await + } + + /// Join a multicast group. + /// + /// When the send queue is full, this method will return `Poll::Pending` + /// and register the current task to be notified when the queue has space available. + pub fn poll_join_multicast_group(&self, addr: T, cx: &mut Context<'_>) -> Poll> where T: Into, { let addr = addr.into(); self.with_mut(|s, i| { - s.iface - .join_multicast_group(&mut i.device, addr, instant_to_smoltcp(Instant::now())) + let mut smoldev = DriverAdapter { + cx: Some(cx), + inner: &mut i.device, + }; + + match s + .iface + .join_multicast_group(&mut smoldev, addr, instant_to_smoltcp(Instant::now())) + { + Ok(announce_sent) => Poll::Ready(Ok(announce_sent)), + Err(MulticastError::Exhausted) => Poll::Pending, + Err(other) => Poll::Ready(Err(other)), + } }) } /// Leave a multicast group. - pub fn leave_multicast_group(&self, addr: T) -> Result + pub async fn leave_multicast_group(&self, addr: T) -> Result + where + T: Into, + { + let addr = addr.into(); + + poll_fn(move |cx| self.poll_leave_multicast_group(addr, cx)).await + } + + /// Leave a multicast group. + /// + /// When the send queue is full, this method will return `Poll::Pending` + /// and register the current task to be notified when the queue has space available. + pub fn poll_leave_multicast_group(&self, addr: T, cx: &mut Context<'_>) -> Poll> where T: Into, { let addr = addr.into(); self.with_mut(|s, i| { - s.iface - .leave_multicast_group(&mut i.device, addr, instant_to_smoltcp(Instant::now())) + let mut smoldev = DriverAdapter { + cx: Some(cx), + inner: &mut i.device, + }; + + match s + .iface + .leave_multicast_group(&mut smoldev, addr, instant_to_smoltcp(Instant::now())) + { + Ok(leave_sent) => Poll::Ready(Ok(leave_sent)), + Err(MulticastError::Exhausted) => Poll::Pending, + Err(other) => Poll::Ready(Err(other)), + } }) } From a1d3bc30fa44795e6e64ba0db8607f9ea65c55a2 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 18 Jul 2023 18:15:35 +0200 Subject: [PATCH 126/148] net-esp-hosted: build docs. --- .github/ci/doc.sh | 1 + embassy-net-esp-hosted/Cargo.toml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 9e9c78a4..06c6fa00 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -37,6 +37,7 @@ docserver-builder -i ./embassy-usb-logger -o webroot/crates/embassy-usb-logger/g docserver-builder -i ./cyw43 -o webroot/crates/cyw43/git.zup docserver-builder -i ./cyw43-pio -o webroot/crates/cyw43-pio/git.zup docserver-builder -i ./embassy-net-w5500 -o webroot/crates/embassy-net-w5500/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 export KUBECONFIG=/ci/secrets/kubeconfig.yml diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml index 26f5b40b..0053c49a 100644 --- a/embassy-net-esp-hosted/Cargo.toml +++ b/embassy-net-esp-hosted/Cargo.toml @@ -18,3 +18,9 @@ embedded-hal-async = { version = "=0.2.0-alpha.2" } noproto = { git="https://github.com/embassy-rs/noproto", default-features = false, features = ["derive"] } #noproto = { version = "0.1", path = "/home/dirbaio/noproto", default-features = false, features = ["derive"] } heapless = "0.7.16" + +[package.metadata.embassy_docs] +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 From c333d855fca0743de1d58ef14e3c2f6389f73145 Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Tue, 18 Jul 2023 17:13:43 -0400 Subject: [PATCH 127/148] Remove merge error --- embassy-nrf/src/pdm.rs | 2 +- examples/nrf/Cargo.toml | 37 ------------------------------------- 2 files changed, 1 insertion(+), 38 deletions(-) delete mode 100644 examples/nrf/Cargo.toml diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index 1fc717fd..f2675bb7 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -463,4 +463,4 @@ macro_rules! impl_pdm { type Interrupt = crate::interrupt::typelevel::$irq; } }; -} \ No newline at end of file +} diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml deleted file mode 100644 index 8309dda0..00000000 --- a/examples/nrf/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -edition = "2021" -name = "embassy-nrf-examples" -version = "0.1.0" - -[features] -default = ["nightly"] -nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embassy-usb-serial", "embassy-usb-hid", "embassy-usb-ncm", "embedded-io/async", "embassy-net"] - -[dependencies] -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", 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"] } -embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } -embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } -embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"], optional = true } -embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"], optional = true } -embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"], optional = true } -embedded-io = "0.3.0" - -defmt = "0.3" -defmt-rtt = "0.3" - -static_cell = "1.0" -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"] } -futures = { version = "0.3.17", default-features = false, features = ["async-await"] } -rand = { version = "0.8.4", default-features = false } -fixed = "1.10.0" -embedded-storage = "0.3.0" -usbd-hid = "0.5.2" -serde = { version = "1.0.136", default-features = false } -num-integer = { version = "0.1.45", default-features = false } -microfft = "0.5.0" From 2c01f277c27bc6ca4f3d41ac57aa1ea24868cfc1 Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Tue, 18 Jul 2023 17:17:04 -0400 Subject: [PATCH 128/148] cargo fmt --- embassy-nrf/src/pdm.rs | 26 ++++++--- examples/nrf52840/src/bin/pdm.rs | 8 ++- examples/nrf52840/src/bin/pdm_continuous.rs | 65 +++++++++++---------- 3 files changed, 56 insertions(+), 43 deletions(-) diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index f2675bb7..48668c7f 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -8,17 +8,17 @@ use core::task::Poll; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::{into_ref, PeripheralRef}; -use futures::future::poll_fn; use fixed::types::I7F1; +use futures::future::poll_fn; use crate::chip::EASY_DMA_SIZE; use crate::gpio::sealed::Pin; use crate::gpio::{AnyPin, Pin as GpioPin}; use crate::interrupt::typelevel::Interrupt; -use crate::{interrupt, Peripheral}; use crate::pac::pdm::mode::{EDGE_A, OPERATION_A}; pub use crate::pac::pdm::pdmclkctrl::FREQ_A as Frequency; pub use crate::pac::pdm::ratio::RATIO_A as Ratio; +use crate::{interrupt, Peripheral}; /// Interrupt handler. pub struct InterruptHandler { @@ -133,8 +133,14 @@ impl<'d, T: Instance> Pdm<'d, T> { } fn _set_gain(r: &crate::pac::pdm::RegisterBlock, gain_left: I7F1, gain_right: I7F1) { - let gain_left = gain_left.saturating_add(I7F1::from_bits(40)).saturating_to_num::().clamp(0, 0x50); - let gain_right = gain_right.saturating_add(I7F1::from_bits(40)).saturating_to_num::().clamp(0, 0x50); + let gain_left = gain_left + .saturating_add(I7F1::from_bits(40)) + .saturating_to_num::() + .clamp(0, 0x50); + let gain_right = gain_right + .saturating_add(I7F1::from_bits(40)) + .saturating_to_num::() + .clamp(0, 0x50); r.gainl.write(|w| unsafe { w.gainl().bits(gain_left) }); r.gainr.write(|w| unsafe { w.gainr().bits(gain_right) }); @@ -258,7 +264,8 @@ impl<'d, T: Instance> Pdm<'d, T> { &mut self, bufs: &mut [[i16; N]; 2], mut sampler: S, - ) -> Result<(), Error> where + ) -> Result<(), Error> + where S: FnMut(&[i16; N]) -> SamplerState, { let r = T::regs(); @@ -267,7 +274,9 @@ impl<'d, T: Instance> Pdm<'d, T> { return Err(Error::AlreadyRunning); } - r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(bufs[0].as_mut_ptr() as u32) }); + r.sample + .ptr + .write(|w| unsafe { w.sampleptr().bits(bufs[0].as_mut_ptr() as u32) }); r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(N as _) }); // Reset and enable the events @@ -285,7 +294,7 @@ impl<'d, T: Instance> Pdm<'d, T> { // wouldn't happen anyway. compiler_fence(Ordering::SeqCst); - r.tasks_start.write(|w| { w.tasks_start().set_bit() }); + r.tasks_start.write(|w| w.tasks_start().set_bit()); let mut current_buffer = 0; @@ -309,7 +318,8 @@ impl<'d, T: Instance> Pdm<'d, T> { r.events_end.reset(); r.intenset.write(|w| w.end().set()); - if !done { // Discard the last buffer after the user requested a stop. + if !done { + // Discard the last buffer after the user requested a stop. if sampler(&bufs[current_buffer]) == SamplerState::Sampled { let next_buffer = 1 - current_buffer; current_buffer = next_buffer; diff --git a/examples/nrf52840/src/bin/pdm.rs b/examples/nrf52840/src/bin/pdm.rs index 47fe6773..444b9137 100644 --- a/examples/nrf52840/src/bin/pdm.rs +++ b/examples/nrf52840/src/bin/pdm.rs @@ -41,9 +41,11 @@ async fn main(_p: Spawner) { buf.iter().min().unwrap(), buf.iter().max().unwrap(), mean, - ( - buf.iter().map(|v| i32::from(*v - mean).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) - / buf.len() as i32).sqrt() as i16, + (buf.iter() + .map(|v| i32::from(*v - mean).pow(2)) + .fold(0i32, |a, b| a.saturating_add(b)) + / buf.len() as i32) + .sqrt() as i16, ); info!("samples: {:?}", &buf); diff --git a/examples/nrf52840/src/bin/pdm_continuous.rs b/examples/nrf52840/src/bin/pdm_continuous.rs index 9eaf3071..7d853147 100644 --- a/examples/nrf52840/src/bin/pdm_continuous.rs +++ b/examples/nrf52840/src/bin/pdm_continuous.rs @@ -2,14 +2,15 @@ #![no_main] #![feature(type_alias_impl_trait)] -use defmt::info; use core::cmp::Ordering; + +use defmt::info; use embassy_executor::Spawner; +use embassy_nrf::pdm::{self, Config, Frequency, OperationMode, Pdm, Ratio, SamplerState}; use embassy_nrf::{bind_interrupts, peripherals}; -use embassy_nrf::pdm::{self, Config, OperationMode, Pdm, SamplerState, Frequency, Ratio}; use fixed::types::I7F1; -use num_integer::Roots; use microfft::real::rfft_1024; +use num_integer::Roots; use {defmt_rtt as _, panic_probe as _}; // Demonstrates both continuous sampling and scanning multiple channels driven by a PPI linked timer @@ -31,34 +32,34 @@ async fn main(_p: Spawner) { let mut bufs = [[0; 1024]; 2]; - pdm - .run_task_sampler( - &mut bufs, - move |buf| { - // NOTE: It is important that the time spent within this callback - // does not exceed the time taken to acquire the 1500 samples we - // have in this example, which would be 10us + 2us per - // sample * 1500 = 18ms. You need to measure the time taken here - // and set the sample buffer size accordingly. Exceeding this - // time can lead to the peripheral re-writing the other buffer. - let mean = (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16; - let (peak_freq_index, peak_mag) = fft_peak_freq(&buf); - let peak_freq = peak_freq_index * 16000 / buf.len(); - info!( - "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}, peak {} @ {} Hz", - buf.len(), - buf.iter().min().unwrap(), - buf.iter().max().unwrap(), - mean, - ( - buf.iter().map(|v| i32::from(*v - mean).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) - / buf.len() as i32).sqrt() as i16, - peak_mag, peak_freq, - ); - SamplerState::Sampled - }, - ) - .await.unwrap(); + pdm.run_task_sampler(&mut bufs, move |buf| { + // NOTE: It is important that the time spent within this callback + // does not exceed the time taken to acquire the 1500 samples we + // have in this example, which would be 10us + 2us per + // sample * 1500 = 18ms. You need to measure the time taken here + // and set the sample buffer size accordingly. Exceeding this + // time can lead to the peripheral re-writing the other buffer. + let mean = (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16; + let (peak_freq_index, peak_mag) = fft_peak_freq(&buf); + let peak_freq = peak_freq_index * 16000 / buf.len(); + info!( + "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}, peak {} @ {} Hz", + buf.len(), + buf.iter().min().unwrap(), + buf.iter().max().unwrap(), + mean, + (buf.iter() + .map(|v| i32::from(*v - mean).pow(2)) + .fold(0i32, |a, b| a.saturating_add(b)) + / buf.len() as i32) + .sqrt() as i16, + peak_mag, + peak_freq, + ); + SamplerState::Sampled + }) + .await + .unwrap(); } fn fft_peak_freq(input: &[i16; 1024]) -> (usize, u32) { @@ -75,6 +76,6 @@ fn fft_peak_freq(input: &[i16; 1024]) -> (usize, u32) { .map(|c| c.norm_sqr()) .enumerate() .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Equal)) - .map(|(i, v)| (i, ((v*32768.0) as u32).sqrt())) + .map(|(i, v)| (i, ((v * 32768.0) as u32).sqrt())) .unwrap() } From be7fbe50d7afe78988509be485d461494d77381a Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Tue, 18 Jul 2023 18:31:32 -0400 Subject: [PATCH 129/148] Update pdm driver to build with all the PACs --- embassy-nrf/src/pdm.rs | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index 48668c7f..4cee566c 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -17,9 +17,16 @@ use crate::gpio::{AnyPin, Pin as GpioPin}; use crate::interrupt::typelevel::Interrupt; use crate::pac::pdm::mode::{EDGE_A, OPERATION_A}; pub use crate::pac::pdm::pdmclkctrl::FREQ_A as Frequency; -pub use crate::pac::pdm::ratio::RATIO_A as Ratio; use crate::{interrupt, Peripheral}; +#[cfg(any( + feature = "nrf52840", + feature = "nrf52833", + feature = "_nrf5340-app", + feature = "_nrf9160", +))] +pub use crate::pac::pdm::ratio::RATIO_A as Ratio; + /// Interrupt handler. pub struct InterruptHandler { _phantom: PhantomData, @@ -111,6 +118,12 @@ impl<'d, T: Instance> Pdm<'d, T> { // configure r.pdmclkctrl.write(|w| w.freq().variant(config.frequency)); + #[cfg(any( + feature = "nrf52840", + feature = "nrf52833", + feature = "_nrf5340-app", + feature = "_nrf9160", + ))] r.ratio.write(|w| w.ratio().variant(config.ratio)); r.mode.write(|w| { w.operation().variant(config.operation_mode.into()); @@ -294,14 +307,14 @@ impl<'d, T: Instance> Pdm<'d, T> { // wouldn't happen anyway. compiler_fence(Ordering::SeqCst); - r.tasks_start.write(|w| w.tasks_start().set_bit()); + r.tasks_start.write(|w| unsafe { w.bits(1) }); let mut current_buffer = 0; let mut done = false; let drop = OnDrop::new(|| { - r.tasks_stop.write(|w| w.tasks_stop().set_bit()); + r.tasks_stop.write(|w| unsafe { w.bits(1) }); // N.B. It would be better if this were async, but Drop only support sync code. while r.events_stopped.read().bits() != 0 {} }); @@ -324,7 +337,7 @@ impl<'d, T: Instance> Pdm<'d, T> { let next_buffer = 1 - current_buffer; current_buffer = next_buffer; } else { - r.tasks_stop.write(|w| w.tasks_stop().set_bit()); + r.tasks_stop.write(|w| unsafe { w.bits(1) }); done = true; }; }; @@ -361,6 +374,12 @@ pub struct Config { /// Clock frequency pub frequency: Frequency, /// Clock ratio + #[cfg(any( + feature = "nrf52840", + feature = "nrf52833", + feature = "_nrf5340-app", + feature = "_nrf9160", + ))] pub ratio: Ratio, /// Gain left in dB pub gain_left: I7F1, @@ -374,6 +393,12 @@ impl Default for Config { operation_mode: OperationMode::Mono, edge: Edge::LeftFalling, frequency: Frequency::DEFAULT, + #[cfg(any( + feature = "nrf52840", + feature = "nrf52833", + feature = "_nrf5340-app", + feature = "_nrf9160", + ))] ratio: Ratio::RATIO80, gain_left: I7F1::ZERO, gain_right: I7F1::ZERO, From 7555a1e3025a45a145734026c0f841d7c6c2625f Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Tue, 18 Jul 2023 18:32:19 -0400 Subject: [PATCH 130/148] cargo fmt --- embassy-nrf/src/pdm.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index 4cee566c..217884d1 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -17,8 +17,6 @@ use crate::gpio::{AnyPin, Pin as GpioPin}; use crate::interrupt::typelevel::Interrupt; use crate::pac::pdm::mode::{EDGE_A, OPERATION_A}; pub use crate::pac::pdm::pdmclkctrl::FREQ_A as Frequency; -use crate::{interrupt, Peripheral}; - #[cfg(any( feature = "nrf52840", feature = "nrf52833", @@ -26,6 +24,7 @@ use crate::{interrupt, Peripheral}; feature = "_nrf9160", ))] pub use crate::pac::pdm::ratio::RATIO_A as Ratio; +use crate::{interrupt, Peripheral}; /// Interrupt handler. pub struct InterruptHandler { From 890d113b855dc11be75a9716401c7703f4ce48e1 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 18 Jul 2023 18:28:12 -0500 Subject: [PATCH 131/148] wpan: fully implement initial draft concept --- embassy-stm32-wpan/src/mac/control.rs | 8 +-- embassy-stm32-wpan/src/mac/driver.rs | 75 ++++++++++++++----------- embassy-stm32-wpan/src/mac/mod.rs | 2 +- embassy-stm32-wpan/src/mac/runner.rs | 21 +++---- embassy-sync/src/channel.rs | 22 ++++++++ examples/stm32wb/src/bin/mac_ffd_net.rs | 2 +- 6 files changed, 80 insertions(+), 50 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs index 6e45e595..2f8a7d07 100644 --- a/embassy-stm32-wpan/src/mac/control.rs +++ b/embassy-stm32-wpan/src/mac/control.rs @@ -6,13 +6,13 @@ pub struct Error { } pub struct Control<'a> { - runner: &'a Runner, + runner: &'a Runner<'a>, } impl<'a> Control<'a> { - pub(crate) fn new(runner: &'a Runner) -> Self { - Self { runner: runner } - } + pub(crate) fn new(runner: &'a Runner<'a>) -> Self { + Self { runner: runner } + } pub async fn init(&mut self) { // TODO diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs index 118f6908..8ebfb2b7 100644 --- a/embassy-stm32-wpan/src/mac/driver.rs +++ b/embassy-stm32-wpan/src/mac/driver.rs @@ -4,16 +4,20 @@ use core::task::Context; use embassy_net_driver::{Capabilities, LinkState, Medium}; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::channel::Channel; +use super::event::MacEvent; +use crate::mac::event::Event; use crate::mac::runner::Runner; use crate::mac::MTU; pub struct Driver<'d> { - runner: &'d Runner, + runner: &'d Runner<'d>, } impl<'d> Driver<'d> { - pub(crate) fn new(runner: &'d Runner) -> Self { + pub(crate) fn new(runner: &'d Runner<'d>) -> Self { Self { runner: runner } } } @@ -21,33 +25,32 @@ impl<'d> Driver<'d> { impl<'d> embassy_net_driver::Driver for Driver<'d> { // type RxToken<'a> = RxToken<'a, 'd> where Self: 'a; // type TxToken<'a> = TxToken<'a, 'd> where Self: 'a; - type RxToken<'a> = RxToken where Self: 'a; - type TxToken<'a> = TxToken where Self: 'a; + type RxToken<'a> = RxToken<'d> where Self: 'a; + type TxToken<'a> = TxToken<'d> where Self: 'a; fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { - self.runner.rx_waker.register(cx.waker()); - - // WAKER.register(cx.waker()); - // if self.rx.available().is_some() && self.tx.available().is_some() { - // Some((RxToken { rx: &mut self.rx }, TxToken { tx: &mut self.tx })) - // } else { - // None - // } - - None + if self.runner.rx_channel.poll_ready_to_receive(cx) && self.runner.tx_channel.poll_ready_to_receive(cx) { + Some(( + RxToken { + rx: &self.runner.rx_channel, + }, + TxToken { + tx: &self.runner.tx_channel, + }, + )) + } else { + None + } } fn transmit(&mut self, cx: &mut Context) -> Option> { - self.runner.tx_waker.register(cx.waker()); - - // WAKER.register(cx.waker()); - // / if self.tx.available().is_some() { - // / Some(TxToken { tx: &mut self.tx }) - // / } else { - // / None - // / } - - None + if self.runner.tx_channel.poll_ready_to_receive(cx) { + Some(TxToken { + tx: &self.runner.tx_channel, + }) + } else { + None + } } fn capabilities(&self) -> Capabilities { @@ -76,30 +79,38 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> { } } -pub struct RxToken { - // rx: &'a mut RDesRing<'d>, +pub struct RxToken<'d> { + rx: &'d Channel, } -impl embassy_net_driver::RxToken for RxToken { +impl<'d> embassy_net_driver::RxToken for RxToken<'d> { fn consume(self, f: F) -> R where F: FnOnce(&mut [u8]) -> R, { - // NOTE(unwrap): we checked the queue wasn't full when creating the token. - // let pkt = unwrap!(self.rx.available()); + // Only valid data events should be put into the queue + + let event = self.rx.try_recv().unwrap(); + let mac_event = event.mac_event().unwrap(); + let data_event = match mac_event { + MacEvent::McpsDataInd(data_event) => data_event, + _ => unreachable!(), + }; let pkt = &mut []; let r = f(&mut pkt[0..]); - // self.rx.pop_packet(); + + // let r = f(&mut data_event.payload()); r } } -pub struct TxToken { +pub struct TxToken<'d> { + tx: &'d Channel, // tx: &'a mut TDesRing<'d>, } -impl embassy_net_driver::TxToken for TxToken { +impl<'d> embassy_net_driver::TxToken for TxToken<'d> { fn consume(self, len: usize, f: F) -> R where F: FnOnce(&mut [u8]) -> R, diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs index 2f9d1c81..3dcda17a 100644 --- a/embassy-stm32-wpan/src/mac/mod.rs +++ b/embassy-stm32-wpan/src/mac/mod.rs @@ -18,7 +18,7 @@ pub use crate::mac::runner::Runner; const MTU: usize = 127; -pub async fn new<'a>(runner: &'a Runner) -> (Control<'a>, Driver<'a>) { +pub async fn new<'a>(runner: &'a Runner<'a>) -> (Control<'a>, Driver<'a>) { (Control::new(runner), Driver::new(runner)) } diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index d545d6c9..911ff60b 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -1,4 +1,6 @@ use embassy_futures::select::{select3, Either3}; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::channel::Channel; use embassy_sync::waitqueue::AtomicWaker; use crate::mac::event::{Event, MacEvent}; @@ -44,22 +46,18 @@ impl TxRing { } } -pub struct Runner { +pub struct Runner<'a> { mac_subsystem: Mac, - pub(crate) rx_ring: Option, - pub(crate) tx_ring: TxRing, - pub(crate) rx_waker: AtomicWaker, - pub(crate) tx_waker: AtomicWaker, + pub(crate) rx_channel: Channel, + pub(crate) tx_channel: Channel, } -impl Runner { +impl<'a> Runner<'a> { pub fn new(mac: Mac) -> Self { Self { mac_subsystem: mac, - rx_ring: None, - tx_ring: TxRing::new(), - rx_waker: AtomicWaker::new(), - tx_waker: AtomicWaker::new(), + rx_channel: Channel::new(), + tx_channel: Channel::new(), } } @@ -73,8 +71,7 @@ impl Runner { if let Ok(evt) = event.mac_event() { match evt { MacEvent::McpsDataInd(data_ind) => { - // TODO: store mac_event in rx_ring - self.rx_waker.wake(); + self.rx_channel.try_send(event); } _ => {} } diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs index 77352874..f421af39 100644 --- a/embassy-sync/src/channel.rs +++ b/embassy-sync/src/channel.rs @@ -335,6 +335,12 @@ impl ChannelState { } } + fn poll_ready_to_receive(&mut self, cx: &mut Context<'_>) -> bool { + self.receiver_waker.register(cx.waker()); + + !self.queue.is_empty() + } + fn try_send(&mut self, message: T) -> Result<(), TrySendError> { self.try_send_with_context(message, None) } @@ -353,6 +359,12 @@ impl ChannelState { } } } + + fn poll_ready_to_send(&mut self, cx: &mut Context<'_>) -> bool { + self.senders_waker.register(cx.waker()); + + !self.queue.is_full() + } } /// A bounded channel for communicating between asynchronous tasks @@ -401,6 +413,16 @@ where self.lock(|c| c.try_send_with_context(m, cx)) } + /// Allows a poll_fn to poll until the channel is ready to receive + pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool { + 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 { + self.lock(|c| c.poll_ready_to_send(cx)) + } + /// Get a sender for this channel. pub fn sender(&self) -> Sender<'_, M, T, N> { Sender { channel: self } diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs index b1cf051b..6072f418 100644 --- a/examples/stm32wb/src/bin/mac_ffd_net.rs +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs @@ -25,7 +25,7 @@ async fn run_mm_queue(memory_manager: mm::MemoryManager) { } #[embassy_executor::task] -async fn run_mac(runner: &'static Runner) { +async fn run_mac(runner: &'static Runner<'static>) { runner.run().await; } From ca1d4179a792d4a33b4f2b97b33002759fd28a21 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 18 Jul 2023 20:52:03 -0500 Subject: [PATCH 132/148] wpan: implement initial event loop --- embassy-stm32-wpan/Cargo.toml | 4 +- embassy-stm32-wpan/src/mac/driver.rs | 22 +++-- embassy-stm32-wpan/src/mac/runner.rs | 113 ++++++++++++------------ examples/stm32wb/Cargo.toml | 6 +- examples/stm32wb/src/bin/mac_ffd_net.rs | 10 ++- 5 files changed, 85 insertions(+), 70 deletions(-) diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 082d00f1..ab58714d 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -18,6 +18,7 @@ embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel", optional=true } +embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver", optional=true } defmt = { version = "0.3", optional = true } cortex-m = "0.7.6" @@ -27,13 +28,14 @@ aligned = "0.4.1" bit_field = "0.10.2" stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } stm32wb-hci = { version = "0.1.3", optional = true } +futures = { version = "0.3.17", default-features = false, features = ["async-await"] } bitflags = { version = "2.3.3", optional = true } [features] defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"] ble = ["dep:stm32wb-hci"] -mac = ["dep:bitflags", "dep:embassy-net-driver-channel"] +mac = ["dep:bitflags", "dep:embassy-net-driver-channel", "dep:embassy-net-driver"] stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs index 8ebfb2b7..a41b7509 100644 --- a/embassy-stm32-wpan/src/mac/driver.rs +++ b/embassy-stm32-wpan/src/mac/driver.rs @@ -29,13 +29,14 @@ 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_channel.poll_ready_to_receive(cx) { + if self.runner.rx_channel.poll_ready_to_receive(cx) && self.runner.tx_buf_channel.poll_ready_to_receive(cx) { Some(( RxToken { rx: &self.runner.rx_channel, }, TxToken { tx: &self.runner.tx_channel, + tx_buf: &self.runner.tx_buf_channel, }, )) } else { @@ -44,9 +45,10 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> { } fn transmit(&mut self, cx: &mut Context) -> Option> { - if self.runner.tx_channel.poll_ready_to_receive(cx) { + if self.runner.tx_buf_channel.poll_ready_to_receive(cx) { Some(TxToken { tx: &self.runner.tx_channel, + tx_buf: &self.runner.tx_buf_channel, }) } else { None @@ -106,8 +108,8 @@ impl<'d> embassy_net_driver::RxToken for RxToken<'d> { } pub struct TxToken<'d> { - tx: &'d Channel, - // tx: &'a mut TDesRing<'d>, + tx: &'d Channel, + tx_buf: &'d Channel, } impl<'d> embassy_net_driver::TxToken for TxToken<'d> { @@ -115,11 +117,13 @@ impl<'d> embassy_net_driver::TxToken for TxToken<'d> { where F: FnOnce(&mut [u8]) -> R, { - // NOTE(unwrap): we checked the queue wasn't full when creating the token. - // let pkt = unwrap!(self.tx.available()); - let pkt = &mut []; - let r = f(&mut pkt[..len]); - // self.tx.transmit(len); + // Only valid tx buffers should be put into the queue + let buf = self.tx_buf.try_recv().unwrap(); + let r = f(&mut buf[..len]); + + // The tx channel should always be of equal capacity to the tx_buf channel + self.tx.try_send(buf).unwrap(); + r } } diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index 911ff60b..9edcff9b 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -1,83 +1,80 @@ -use embassy_futures::select::{select3, Either3}; +use embassy_futures::join; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; -use embassy_sync::waitqueue::AtomicWaker; +use crate::mac::commands::DataRequest; use crate::mac::event::{Event, MacEvent}; +use crate::mac::typedefs::{AddressMode, MacAddress, PanId, SecurityLevel}; use crate::mac::MTU; use crate::sub::mac::Mac; -pub(crate) struct TxRing { - // stores n packets of up to mtu size - ring: [[u8; MTU]; 5], - pending: bool, - // start: u8, - // end: u8, -} - -impl TxRing { - pub(crate) fn new() -> Self { - Self { - ring: [[0; MTU]; 5], - pending: false, - } - } - - // wait for a free packet to become available - pub fn is_packet_free(&self) -> bool { - !self.pending - } - - // get the next available free packet - pub fn get_free_packet<'a>(&'a mut self) -> &'a mut [u8] { - self.pending = true; - - &mut self.ring[0] - } - - pub fn get_packet_to_transmit<'a>(&'a mut self) -> Option<&'a [u8]> { - if self.pending { - self.pending = false; - - Some(&self.ring[0]) - } else { - None - } - } -} - pub struct Runner<'a> { mac_subsystem: Mac, pub(crate) rx_channel: Channel, - pub(crate) tx_channel: Channel, + pub(crate) tx_channel: Channel, + pub(crate) tx_buf_channel: Channel, } impl<'a> Runner<'a> { - pub fn new(mac: Mac) -> Self { - Self { + pub fn new(mac: Mac, tx_buf_queue: [&'a mut [u8; MTU]; 5]) -> Self { + let this = Self { mac_subsystem: mac, rx_channel: Channel::new(), tx_channel: Channel::new(), - } - } + tx_buf_channel: Channel::new(), + }; - pub(crate) async fn init(&mut self, firmware: &[u8]) { - debug!("wifi init done"); + for buf in tx_buf_queue { + this.tx_buf_channel.try_send(buf).unwrap(); + } + + this } pub async fn run(&self) -> ! { - loop { - let event = self.mac_subsystem.read().await; - if let Ok(evt) = event.mac_event() { - match evt { - MacEvent::McpsDataInd(data_ind) => { - self.rx_channel.try_send(event); + join::join( + async { + loop { + let event = self.mac_subsystem.read().await; + if let Ok(evt) = event.mac_event() { + match evt { + MacEvent::McpsDataInd(_) => { + self.rx_channel.send(event).await; + } + _ => {} + } } - _ => {} } - } + }, + async { + loop { + let buf = self.tx_channel.recv().await; - // TODO: select tx event - } + self.mac_subsystem + .send_command( + DataRequest { + src_addr_mode: AddressMode::Short, + dst_addr_mode: AddressMode::Short, + dst_pan_id: PanId([0x1A, 0xAA]), + dst_address: MacAddress::BROADCAST, + msdu_handle: 0x02, + ack_tx: 0x00, + gts_tx: false, + security_level: SecurityLevel::Unsecure, + ..Default::default() + } + .set_buffer(&buf), + ) + .await + .unwrap(); + + // The tx channel should always be of equal capacity to the tx_buf channel + self.tx_buf_channel.try_send(buf).unwrap(); + } + }, + ) + .await; + + loop {} } } diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 8585b99f..7c0b83e6 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -21,7 +21,7 @@ embedded-hal = "0.2.6" panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } - +static_cell = { version = "1.1", features = ["nightly"]} [features] default = ["ble", "mac"] @@ -40,6 +40,10 @@ required-features = ["mac"] name = "mac_ffd" required-features = ["mac"] +[[bin]] +name = "mac_ffd_net" +required-features = ["mac"] + [[bin]] name = "eddystone_beacon" required-features = ["ble"] diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs index 6072f418..7b8c4b9d 100644 --- a/examples/stm32wb/src/bin/mac_ffd_net.rs +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs @@ -172,7 +172,15 @@ async fn main(spawner: Spawner) { defmt::info!("{:#x}", evt.mac_event()); } - let runner = make_static!(Runner::new(mbox.mac_subsystem)); + let tx_queue = [ + make_static!([0u8; 127]), + make_static!([0u8; 127]), + make_static!([0u8; 127]), + make_static!([0u8; 127]), + make_static!([0u8; 127]), + ]; + + let runner = make_static!(Runner::new(mbox.mac_subsystem, tx_queue)); spawner.spawn(run_mac(runner)).unwrap(); From 3df2c71e6c27eedacef1ddd822537c8762fe0578 Mon Sep 17 00:00:00 2001 From: Alessandro Pezzato Date: Tue, 18 Jul 2023 22:24:52 +0200 Subject: [PATCH 133/148] stm32/uart: add swap_rx_tx --- embassy-stm32/src/usart/mod.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index c97efbf0..1ba182e2 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -116,6 +116,10 @@ pub struct Config { /// but will effectively disable noise detection. #[cfg(not(usart_v1))] pub assume_noise_free: bool, + + /// Set this to true to swap the RX and TX pins. + #[cfg(any(usart_v3, usart_v4))] + pub swap_rx_tx: bool, } impl Default for Config { @@ -129,6 +133,8 @@ impl Default for Config { detect_previous_overrun: false, #[cfg(not(usart_v1))] assume_noise_free: false, + #[cfg(any(usart_v3, usart_v4))] + swap_rx_tx: false, } } } @@ -688,8 +694,20 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { let r = T::regs(); - rx.set_as_af(rx.af_num(), AFType::Input); - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); + #[allow(unused_variables)] + let swap_rx_tx = false; + + #[cfg(any(usart_v3, usart_v4))] + let swap_rx_tx = config.swap_rx_tx; + + if swap_rx_tx { + let (rx, tx) = (tx, rx); + rx.set_as_af(rx.af_num(), AFType::Input); + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); + } else { + rx.set_as_af(rx.af_num(), AFType::Input); + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); + } configure(r, &config, T::frequency(), T::KIND, true, true); @@ -847,6 +865,9 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: StopBits::STOP1P5 => vals::Stop::STOP1P5, StopBits::STOP2 => vals::Stop::STOP2, }); + + #[cfg(any(usart_v3, usart_v4))] + w.set_swap(config.swap_rx_tx); }); r.cr1().write(|w| { // enable uart From 36ff688fab8bb0a17f001cdf62f24884e3ac1f33 Mon Sep 17 00:00:00 2001 From: Alessandro Pezzato Date: Wed, 19 Jul 2023 10:50:40 +0200 Subject: [PATCH 134/148] stm32/uart: optimize swap_rx_tx --- embassy-stm32/src/usart/mod.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 1ba182e2..ea8e525e 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -694,19 +694,21 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { let r = T::regs(); - #[allow(unused_variables)] - let swap_rx_tx = false; - - #[cfg(any(usart_v3, usart_v4))] - let swap_rx_tx = config.swap_rx_tx; - - if swap_rx_tx { - let (rx, tx) = (tx, rx); - rx.set_as_af(rx.af_num(), AFType::Input); - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); - } else { - rx.set_as_af(rx.af_num(), AFType::Input); - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); + // Some chips do not have swap_rx_tx bit + cfg_if::cfg_if! { + if #[cfg(any(usart_v3, usart_v4))] { + if config.swap_rx_tx { + let (rx, tx) = (tx, rx); + rx.set_as_af(rx.af_num(), AFType::Input); + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); + } else { + rx.set_as_af(rx.af_num(), AFType::Input); + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); + } + } else { + rx.set_as_af(rx.af_num(), AFType::Input); + tx.set_as_af(tx.af_num(), AFType::OutputPushPull); + } } configure(r, &config, T::frequency(), T::KIND, true, true); From 28254842db645bc961d19fa2287610b7b1d3447c Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 19 Jul 2023 17:49:08 -0500 Subject: [PATCH 135/148] - optimize event to parse opcode only once - optimze channels - return mut ref for smoltcp rx --- embassy-stm32-wpan/Cargo.toml | 3 +- embassy-stm32-wpan/src/mac/control.rs | 1 + embassy-stm32-wpan/src/mac/driver.rs | 23 ++-- embassy-stm32-wpan/src/mac/event.rs | 123 +++++++++++++++------- embassy-stm32-wpan/src/mac/indications.rs | 4 +- embassy-stm32-wpan/src/mac/mod.rs | 7 -- embassy-stm32-wpan/src/mac/runner.rs | 19 ++-- embassy-stm32-wpan/src/sub/mac.rs | 2 +- examples/stm32wb/src/bin/mac_ffd.rs | 34 +++--- examples/stm32wb/src/bin/mac_ffd_net.rs | 28 ++--- examples/stm32wb/src/bin/mac_rfd.rs | 34 +++--- tests/stm32/src/bin/wpan_mac.rs | 33 +++--- 12 files changed, 178 insertions(+), 133 deletions(-) diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index ab58714d..6cd12220 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -17,7 +17,6 @@ embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } -embassy-net-driver-channel = { version = "0.1.0", path = "../embassy-net-driver-channel", optional=true } embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver", optional=true } defmt = { version = "0.3", optional = true } @@ -35,7 +34,7 @@ bitflags = { version = "2.3.3", optional = true } defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"] ble = ["dep:stm32wb-hci"] -mac = ["dep:bitflags", "dep:embassy-net-driver-channel", "dep:embassy-net-driver"] +mac = ["dep:bitflags", "dep:embassy-net-driver" ] stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs index 2f8a7d07..c45f6407 100644 --- a/embassy-stm32-wpan/src/mac/control.rs +++ b/embassy-stm32-wpan/src/mac/control.rs @@ -6,6 +6,7 @@ pub struct Error { } pub struct Control<'a> { + #[allow(dead_code)] runner: &'a Runner<'a>, } diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs index a41b7509..3017808f 100644 --- a/embassy-stm32-wpan/src/mac/driver.rs +++ b/embassy-stm32-wpan/src/mac/driver.rs @@ -7,8 +7,7 @@ use embassy_net_driver::{Capabilities, LinkState, Medium}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; -use super::event::MacEvent; -use crate::mac::event::Event; +use crate::mac::event::{Event, MacEvent}; use crate::mac::runner::Runner; use crate::mac::MTU; @@ -64,7 +63,7 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> { caps } - fn link_state(&mut self, cx: &mut Context) -> LinkState { + fn link_state(&mut self, _cx: &mut Context) -> LinkState { // if self.phy.poll_link(&mut self.station_management, cx) { // LinkState::Up // } else { @@ -82,7 +81,7 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> { } pub struct RxToken<'d> { - rx: &'d Channel, + rx: &'d Channel, 1>, } impl<'d> embassy_net_driver::RxToken for RxToken<'d> { @@ -92,24 +91,18 @@ impl<'d> embassy_net_driver::RxToken for RxToken<'d> { { // Only valid data events should be put into the queue - let event = self.rx.try_recv().unwrap(); - let mac_event = event.mac_event().unwrap(); - let data_event = match mac_event { + let data_event = match *self.rx.try_recv().unwrap() { MacEvent::McpsDataInd(data_event) => data_event, _ => unreachable!(), }; - let pkt = &mut []; - let r = f(&mut pkt[0..]); - - // let r = f(&mut data_event.payload()); - r + f(&mut data_event.payload()) } } pub struct TxToken<'d> { - tx: &'d Channel, - tx_buf: &'d Channel, + tx: &'d Channel, + tx_buf: &'d Channel, } impl<'d> embassy_net_driver::TxToken for TxToken<'d> { @@ -122,7 +115,7 @@ impl<'d> embassy_net_driver::TxToken for TxToken<'d> { let r = f(&mut buf[..len]); // The tx channel should always be of equal capacity to the tx_buf channel - self.tx.try_send(buf).unwrap(); + self.tx.try_send((buf, len)).unwrap(); r } diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs index a2bb7922..d975c5bd 100644 --- a/embassy-stm32-wpan/src/mac/event.rs +++ b/embassy-stm32-wpan/src/mac/event.rs @@ -1,4 +1,4 @@ -use core::mem; +use core::{mem, ops}; use super::indications::{ AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication, @@ -22,55 +22,104 @@ pub(crate) trait ParseableMacEvent: Sized { } } -pub struct Event { +pub struct Event<'a> { + #[allow(dead_code)] event_box: EvtBox, + mac_event: MacEvent<'a>, } -impl Event { - pub(crate) fn new(event_box: EvtBox) -> Self { - Self { event_box } - } - - pub fn mac_event<'a>(&'a self) -> Result, ()> { - let payload = self.event_box.payload(); +impl<'a> Event<'a> { + pub(crate) fn new(event_box: EvtBox) -> Result { + let payload = event_box.payload(); let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap()); let opcode = OpcodeM0ToM4::try_from(opcode)?; let buf = &payload[2..]; - match opcode { - OpcodeM0ToM4::MlmeAssociateCnf => Ok(MacEvent::MlmeAssociateCnf(AssociateConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeDisassociateCnf => { - Ok(MacEvent::MlmeDisassociateCnf(DisassociateConfirm::from_buffer(buf)?)) + // To avoid re-parsing the opcode, we store the result of the parse + // this requires use of unsafe because rust cannot assume that a reference will become + // invalid when the underlying result is moved. However, because we refer to a "heap" + // allocation, the underlying reference will not move until the struct is dropped. + + let mac_event = match opcode { + OpcodeM0ToM4::MlmeAssociateCnf => { + MacEvent::MlmeAssociateCnf(unsafe { &*(AssociateConfirm::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmeDisassociateCnf => { + MacEvent::MlmeDisassociateCnf(unsafe { &*(DisassociateConfirm::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmeGetCnf => MacEvent::MlmeGetCnf(unsafe { &*(GetConfirm::from_buffer(buf)? as *const _) }), + OpcodeM0ToM4::MlmeGtsCnf => MacEvent::MlmeGtsCnf(unsafe { &*(GtsConfirm::from_buffer(buf)? as *const _) }), + OpcodeM0ToM4::MlmeResetCnf => { + MacEvent::MlmeResetCnf(unsafe { &*(ResetConfirm::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmeRxEnableCnf => { + MacEvent::MlmeRxEnableCnf(unsafe { &*(RxEnableConfirm::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmeScanCnf => { + MacEvent::MlmeScanCnf(unsafe { &*(ScanConfirm::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmeSetCnf => MacEvent::MlmeSetCnf(unsafe { &*(SetConfirm::from_buffer(buf)? as *const _) }), + OpcodeM0ToM4::MlmeStartCnf => { + MacEvent::MlmeStartCnf(unsafe { &*(StartConfirm::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmePollCnf => { + MacEvent::MlmePollCnf(unsafe { &*(PollConfirm::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmeDpsCnf => MacEvent::MlmeDpsCnf(unsafe { &*(DpsConfirm::from_buffer(buf)? as *const _) }), + OpcodeM0ToM4::MlmeSoundingCnf => { + MacEvent::MlmeSoundingCnf(unsafe { &*(SoundingConfirm::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmeCalibrateCnf => { + MacEvent::MlmeCalibrateCnf(unsafe { &*(CalibrateConfirm::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::McpsDataCnf => { + MacEvent::McpsDataCnf(unsafe { &*(DataConfirm::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::McpsPurgeCnf => { + MacEvent::McpsPurgeCnf(unsafe { &*(PurgeConfirm::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmeAssociateInd => { + MacEvent::MlmeAssociateInd(unsafe { &*(AssociateIndication::from_buffer(buf)? as *const _) }) } - OpcodeM0ToM4::MlmeGetCnf => Ok(MacEvent::MlmeGetCnf(GetConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeGtsCnf => Ok(MacEvent::MlmeGtsCnf(GtsConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeResetCnf => Ok(MacEvent::MlmeResetCnf(ResetConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeRxEnableCnf => Ok(MacEvent::MlmeRxEnableCnf(RxEnableConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeScanCnf => Ok(MacEvent::MlmeScanCnf(ScanConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeSetCnf => Ok(MacEvent::MlmeSetCnf(SetConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeStartCnf => Ok(MacEvent::MlmeStartCnf(StartConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::MlmePollCnf => Ok(MacEvent::MlmePollCnf(PollConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeDpsCnf => Ok(MacEvent::MlmeDpsCnf(DpsConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeSoundingCnf => Ok(MacEvent::MlmeSoundingCnf(SoundingConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeCalibrateCnf => Ok(MacEvent::MlmeCalibrateCnf(CalibrateConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::McpsDataCnf => Ok(MacEvent::McpsDataCnf(DataConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::McpsPurgeCnf => Ok(MacEvent::McpsPurgeCnf(PurgeConfirm::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeAssociateInd => Ok(MacEvent::MlmeAssociateInd(AssociateIndication::from_buffer(buf)?)), OpcodeM0ToM4::MlmeDisassociateInd => { - Ok(MacEvent::MlmeDisassociateInd(DisassociateIndication::from_buffer(buf)?)) + MacEvent::MlmeDisassociateInd(unsafe { &*(DisassociateIndication::from_buffer(buf)? as *const _) }) } OpcodeM0ToM4::MlmeBeaconNotifyInd => { - Ok(MacEvent::MlmeBeaconNotifyInd(BeaconNotifyIndication::from_buffer(buf)?)) + MacEvent::MlmeBeaconNotifyInd(unsafe { &*(BeaconNotifyIndication::from_buffer(buf)? as *const _) }) } - OpcodeM0ToM4::MlmeCommStatusInd => Ok(MacEvent::MlmeCommStatusInd(CommStatusIndication::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeGtsInd => Ok(MacEvent::MlmeGtsInd(GtsIndication::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeOrphanInd => Ok(MacEvent::MlmeOrphanInd(OrphanIndication::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeSyncLossInd => Ok(MacEvent::MlmeSyncLossInd(SyncLossIndication::from_buffer(buf)?)), - OpcodeM0ToM4::MlmeDpsInd => Ok(MacEvent::MlmeDpsInd(DpsIndication::from_buffer(buf)?)), - OpcodeM0ToM4::McpsDataInd => Ok(MacEvent::McpsDataInd(DataIndication::from_buffer(buf)?)), - OpcodeM0ToM4::MlmePollInd => Ok(MacEvent::MlmePollInd(PollIndication::from_buffer(buf)?)), - } + OpcodeM0ToM4::MlmeCommStatusInd => { + MacEvent::MlmeCommStatusInd(unsafe { &*(CommStatusIndication::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmeGtsInd => { + MacEvent::MlmeGtsInd(unsafe { &*(GtsIndication::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmeOrphanInd => { + MacEvent::MlmeOrphanInd(unsafe { &*(OrphanIndication::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmeSyncLossInd => { + MacEvent::MlmeSyncLossInd(unsafe { &*(SyncLossIndication::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmeDpsInd => { + MacEvent::MlmeDpsInd(unsafe { &*(DpsIndication::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::McpsDataInd => { + MacEvent::McpsDataInd(unsafe { &*(DataIndication::from_buffer(buf)? as *const _) }) + } + OpcodeM0ToM4::MlmePollInd => { + MacEvent::MlmePollInd(unsafe { &*(PollIndication::from_buffer(buf)? as *const _) }) + } + }; + + Ok(Self { event_box, mac_event }) + } +} + +impl<'a> ops::Deref for Event<'a> { + type Target = MacEvent<'a>; + + fn deref(&self) -> &Self::Target { + &self.mac_event } } diff --git a/embassy-stm32-wpan/src/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs index 5445fb4a..4349af9c 100644 --- a/embassy-stm32-wpan/src/mac/indications.rs +++ b/embassy-stm32-wpan/src/mac/indications.rs @@ -236,8 +236,8 @@ pub struct DataIndication { impl ParseableMacEvent for DataIndication {} impl DataIndication { - pub fn payload<'a>(&'a self) -> &'a [u8] { - unsafe { slice::from_raw_parts(self.msdu_ptr, self.msdu_length as usize) } + pub fn payload<'a>(&'a self) -> &'a mut [u8] { + unsafe { slice::from_raw_parts_mut(self.msdu_ptr as *mut _, self.msdu_length as usize) } } } diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs index 3dcda17a..a93f7a69 100644 --- a/embassy-stm32-wpan/src/mac/mod.rs +++ b/embassy-stm32-wpan/src/mac/mod.rs @@ -10,8 +10,6 @@ pub mod responses; pub mod runner; pub mod typedefs; -use core::slice; - pub use crate::mac::control::{Control, Error as ControlError}; use crate::mac::driver::Driver; pub use crate::mac::runner::Runner; @@ -21,8 +19,3 @@ const MTU: usize = 127; pub async fn new<'a>(runner: &'a Runner<'a>) -> (Control<'a>, Driver<'a>) { (Control::new(runner), Driver::new(runner)) } - -fn slice8_mut(x: &mut [u32]) -> &mut [u8] { - let len = x.len() * 4; - unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) } -} diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index 9edcff9b..779712cd 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -10,9 +10,9 @@ use crate::sub::mac::Mac; pub struct Runner<'a> { mac_subsystem: Mac, - pub(crate) rx_channel: Channel, - pub(crate) tx_channel: Channel, - pub(crate) tx_buf_channel: Channel, + pub(crate) rx_channel: Channel, 1>, + pub(crate) tx_channel: Channel, + pub(crate) tx_buf_channel: Channel, } impl<'a> Runner<'a> { @@ -31,15 +31,14 @@ impl<'a> Runner<'a> { this } - pub async fn run(&self) -> ! { + pub async fn run(&'a self) -> ! { join::join( async { loop { - let event = self.mac_subsystem.read().await; - if let Ok(evt) = event.mac_event() { - match evt { + if let Ok(mac_event) = self.mac_subsystem.read().await { + match *mac_event { MacEvent::McpsDataInd(_) => { - self.rx_channel.send(event).await; + self.rx_channel.send(mac_event).await; } _ => {} } @@ -48,7 +47,7 @@ impl<'a> Runner<'a> { }, async { loop { - let buf = self.tx_channel.recv().await; + let (buf, len) = self.tx_channel.recv().await; self.mac_subsystem .send_command( @@ -63,7 +62,7 @@ impl<'a> Runner<'a> { security_level: SecurityLevel::Unsecure, ..Default::default() } - .set_buffer(&buf), + .set_buffer(&buf[..len]), ) .await .unwrap(); diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs index d9bf4c90..5ecbfe8c 100644 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ b/embassy-stm32-wpan/src/sub/mac.rs @@ -94,7 +94,7 @@ impl Mac { } } - pub async fn read(&self) -> Event { + pub async fn read(&self) -> Result, ()> { Event::new(self.tl_read().await) } } diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index bc71e29a..7de30778 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -74,8 +74,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("setting extended address"); @@ -88,8 +88,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("setting short address"); @@ -102,8 +102,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("setting association permit"); @@ -116,8 +116,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("setting TX power"); @@ -130,8 +130,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("starting FFD device"); @@ -148,8 +148,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("setting RX on when idle"); @@ -162,17 +162,17 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } loop { let evt = mbox.mac_subsystem.read().await; - if let Ok(evt) = evt.mac_event() { + if let Ok(evt) = evt { defmt::info!("parsed mac event"); - defmt::info!("{:#x}", evt); + defmt::info!("{:#x}", *evt); - match evt { + match *evt { MacEvent::MlmeAssociateInd(association) => mbox .mac_subsystem .send_command(&AssociateResponse { diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs index 7b8c4b9d..16c33e14 100644 --- a/examples/stm32wb/src/bin/mac_ffd_net.rs +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs @@ -80,8 +80,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("setting extended address"); @@ -94,8 +94,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("setting short address"); @@ -108,8 +108,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("setting association permit"); @@ -122,8 +122,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("setting TX power"); @@ -136,8 +136,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("starting FFD device"); @@ -154,8 +154,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("setting RX on when idle"); @@ -168,8 +168,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } let tx_queue = [ diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index 7cb401d8..d1307a84 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -76,8 +76,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("setting extended address"); @@ -90,8 +90,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - defmt::info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + defmt::info!("{:#x}", *evt); } info!("getting extended address"); @@ -104,10 +104,10 @@ async fn main(spawner: Spawner) { .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + info!("{:#x}", *evt); - if let Ok(MacEvent::MlmeGetCnf(evt)) = evt.mac_event() { + if let MacEvent::MlmeGetCnf(evt) = *evt { if evt.pib_attribute_value_len == 8 { let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; @@ -132,10 +132,10 @@ async fn main(spawner: Spawner) { info!("{}", a); mbox.mac_subsystem.send_command(&a).await.unwrap(); let short_addr = { - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + info!("{:#x}", *evt); - if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt.mac_event() { + if let MacEvent::MlmeAssociateCnf(conf) = *evt { conf.assoc_short_address } else { defmt::panic!() @@ -151,8 +151,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + info!("{:#x}", *evt); } info!("sending data"); @@ -175,12 +175,14 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + info!("{:#x}", *evt); } loop { - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt.mac_event()); + match mbox.mac_subsystem.read().await { + Ok(evt) => info!("{:#x}", *evt), + _ => continue, + }; } } diff --git a/tests/stm32/src/bin/wpan_mac.rs b/tests/stm32/src/bin/wpan_mac.rs index d64a5ef8..2b0d67bb 100644 --- a/tests/stm32/src/bin/wpan_mac.rs +++ b/tests/stm32/src/bin/wpan_mac.rs @@ -56,8 +56,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + info!("{:#x}", *evt); } info!("setting extended address"); @@ -70,8 +70,8 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt.mac_event()); + let evt = mbox.mac_subsystem.read().await.unwrap(); + info!("{:#x}", *evt); } info!("getting extended address"); @@ -82,11 +82,12 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt.mac_event()); - if let Ok(MacEvent::MlmeGetCnf(evt)) = evt.mac_event() { + { + let evt = mbox.mac_subsystem.read().await.unwrap(); + info!("{:#x}", *evt); + + if let MacEvent::MlmeGetCnf(evt) = *evt { if evt.pib_attribute_value_len == 8 { let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; @@ -110,10 +111,18 @@ async fn main(spawner: Spawner) { }; info!("{}", a); mbox.mac_subsystem.send_command(&a).await.unwrap(); - { - let evt = mbox.mac_subsystem.read().await; - info!("{:#x}", evt.mac_event()); - } + let short_addr = { + let evt = mbox.mac_subsystem.read().await.unwrap(); + info!("{:#x}", *evt); + + if let MacEvent::MlmeAssociateCnf(conf) = *evt { + conf.assoc_short_address + } else { + defmt::panic!() + } + }; + + _ = short_addr; info!("Test OK"); cortex_m::asm::bkpt(); From 02d57afd51451fe9e7d224a0ea665a665ba2b72f Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 19 Jul 2023 17:52:07 -0500 Subject: [PATCH 136/148] rustfmt --- examples/stm32wb/src/bin/mac_ffd_net.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs index 16c33e14..a55b1fc7 100644 --- a/examples/stm32wb/src/bin/mac_ffd_net.rs +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs @@ -6,8 +6,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest}; -use embassy_stm32_wpan::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel}; +use embassy_stm32_wpan::mac::commands::{ResetRequest, SetRequest, StartRequest}; +use embassy_stm32_wpan::mac::typedefs::{MacChannel, PanId, PibId}; use embassy_stm32_wpan::mac::{self, Runner}; use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; @@ -185,4 +185,7 @@ async fn main(spawner: Spawner) { spawner.spawn(run_mac(runner)).unwrap(); let (driver, control) = mac::new(runner).await; + + let _ = driver; + let _ = control; } From a3d4ae85b021b888a78ef2214a7ecae0a49741c4 Mon Sep 17 00:00:00 2001 From: pennae Date: Thu, 20 Jul 2023 15:48:59 +0200 Subject: [PATCH 137/148] rp: disable adc hardware on Adc drop the adc constantly pulls a small but significant amount of current while the hardware is enabled. this can have quite an effect on sleeping devices that also use the adc. --- embassy-rp/src/adc.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs index dfa1b877..95780c06 100644 --- a/embassy-rp/src/adc.rs +++ b/embassy-rp/src/adc.rs @@ -81,6 +81,16 @@ pub struct Adc<'d, M: Mode> { phantom: PhantomData<(&'d ADC, M)>, } +impl<'d, M: Mode> Drop for Adc<'d, M> { + fn drop(&mut self) { + let r = Self::regs(); + // disable ADC. leaving it enabled comes with a ~150µA static + // current draw. the temperature sensor has already been disabled + // by the temperature-reading methods, so we don't need to touch that. + r.cs().write(|w| w.set_en(false)); + } +} + impl<'d, M: Mode> Adc<'d, M> { #[inline] fn regs() -> pac::adc::Adc { From 809d3476aac88ddba01cd16f0df3565e35beddea Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 20 Jul 2023 16:45:04 -0500 Subject: [PATCH 138/148] wpan: further optimize mac event --- embassy-stm32-wpan/src/mac/driver.rs | 6 +- embassy-stm32-wpan/src/mac/event.rs | 83 ++++++++++++------------- embassy-stm32-wpan/src/mac/runner.rs | 6 +- embassy-stm32-wpan/src/sub/mac.rs | 10 +-- examples/stm32wb/src/bin/mac_ffd.rs | 39 +++--------- examples/stm32wb/src/bin/mac_ffd_net.rs | 35 +++-------- examples/stm32wb/src/bin/mac_rfd.rs | 24 +++---- tests/stm32/src/bin/wpan_mac.rs | 23 +++---- 8 files changed, 86 insertions(+), 140 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs index 3017808f..fffbb9ed 100644 --- a/embassy-stm32-wpan/src/mac/driver.rs +++ b/embassy-stm32-wpan/src/mac/driver.rs @@ -7,7 +7,7 @@ use embassy_net_driver::{Capabilities, LinkState, Medium}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; -use crate::mac::event::{Event, MacEvent}; +use crate::mac::event::MacEvent; use crate::mac::runner::Runner; use crate::mac::MTU; @@ -81,7 +81,7 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> { } pub struct RxToken<'d> { - rx: &'d Channel, 1>, + rx: &'d Channel, 1>, } impl<'d> embassy_net_driver::RxToken for RxToken<'d> { @@ -91,7 +91,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_recv().unwrap() { MacEvent::McpsDataInd(data_event) => data_event, _ => unreachable!(), }; diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs index d975c5bd..b6f57fda 100644 --- a/embassy-stm32-wpan/src/mac/event.rs +++ b/embassy-stm32-wpan/src/mac/event.rs @@ -1,4 +1,4 @@ -use core::{mem, ops}; +use core::{mem, ptr}; use super::indications::{ AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication, @@ -8,9 +8,9 @@ use super::responses::{ AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm, PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm, }; -use crate::evt::EvtBox; +use crate::evt::{EvtBox, MemoryManager}; use crate::mac::opcodes::OpcodeM0ToM4; -use crate::sub::mac::Mac; +use crate::sub::mac::{self, Mac}; pub(crate) trait ParseableMacEvent: Sized { fn from_buffer<'a>(buf: &'a [u8]) -> Result<&'a Self, ()> { @@ -22,13 +22,36 @@ pub(crate) trait ParseableMacEvent: Sized { } } -pub struct Event<'a> { - #[allow(dead_code)] - event_box: EvtBox, - mac_event: MacEvent<'a>, +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum MacEvent<'a> { + MlmeAssociateCnf(&'a AssociateConfirm), + MlmeDisassociateCnf(&'a DisassociateConfirm), + MlmeGetCnf(&'a GetConfirm), + MlmeGtsCnf(&'a GtsConfirm), + MlmeResetCnf(&'a ResetConfirm), + MlmeRxEnableCnf(&'a RxEnableConfirm), + MlmeScanCnf(&'a ScanConfirm), + MlmeSetCnf(&'a SetConfirm), + MlmeStartCnf(&'a StartConfirm), + MlmePollCnf(&'a PollConfirm), + MlmeDpsCnf(&'a DpsConfirm), + MlmeSoundingCnf(&'a SoundingConfirm), + MlmeCalibrateCnf(&'a CalibrateConfirm), + McpsDataCnf(&'a DataConfirm), + McpsPurgeCnf(&'a PurgeConfirm), + MlmeAssociateInd(&'a AssociateIndication), + MlmeDisassociateInd(&'a DisassociateIndication), + MlmeBeaconNotifyInd(&'a BeaconNotifyIndication), + MlmeCommStatusInd(&'a CommStatusIndication), + MlmeGtsInd(&'a GtsIndication), + MlmeOrphanInd(&'a OrphanIndication), + MlmeSyncLossInd(&'a SyncLossIndication), + MlmeDpsInd(&'a DpsIndication), + McpsDataInd(&'a DataIndication), + MlmePollInd(&'a PollIndication), } -impl<'a> Event<'a> { +impl<'a> MacEvent<'a> { pub(crate) fn new(event_box: EvtBox) -> Result { let payload = event_box.payload(); let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap()); @@ -111,43 +134,17 @@ impl<'a> Event<'a> { } }; - Ok(Self { event_box, mac_event }) + // Forget the event box so that drop isn't called + // We want to handle the lifetime ourselves + + mem::forget(event_box); + + Ok(mac_event) } } -impl<'a> ops::Deref for Event<'a> { - type Target = MacEvent<'a>; - - fn deref(&self) -> &Self::Target { - &self.mac_event +impl<'a> Drop for MacEvent<'a> { + fn drop(&mut self) { + unsafe { mac::Mac::drop_event_packet(ptr::null_mut()) }; } } - -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum MacEvent<'a> { - MlmeAssociateCnf(&'a AssociateConfirm), - MlmeDisassociateCnf(&'a DisassociateConfirm), - MlmeGetCnf(&'a GetConfirm), - MlmeGtsCnf(&'a GtsConfirm), - MlmeResetCnf(&'a ResetConfirm), - MlmeRxEnableCnf(&'a RxEnableConfirm), - MlmeScanCnf(&'a ScanConfirm), - MlmeSetCnf(&'a SetConfirm), - MlmeStartCnf(&'a StartConfirm), - MlmePollCnf(&'a PollConfirm), - MlmeDpsCnf(&'a DpsConfirm), - MlmeSoundingCnf(&'a SoundingConfirm), - MlmeCalibrateCnf(&'a CalibrateConfirm), - McpsDataCnf(&'a DataConfirm), - McpsPurgeCnf(&'a PurgeConfirm), - MlmeAssociateInd(&'a AssociateIndication), - MlmeDisassociateInd(&'a DisassociateIndication), - MlmeBeaconNotifyInd(&'a BeaconNotifyIndication), - MlmeCommStatusInd(&'a CommStatusIndication), - MlmeGtsInd(&'a GtsIndication), - MlmeOrphanInd(&'a OrphanIndication), - MlmeSyncLossInd(&'a SyncLossIndication), - MlmeDpsInd(&'a DpsIndication), - McpsDataInd(&'a DataIndication), - MlmePollInd(&'a PollIndication), -} diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index 779712cd..a0090012 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -3,14 +3,14 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; use crate::mac::commands::DataRequest; -use crate::mac::event::{Event, MacEvent}; +use crate::mac::event::MacEvent; use crate::mac::typedefs::{AddressMode, MacAddress, PanId, SecurityLevel}; use crate::mac::MTU; use crate::sub::mac::Mac; pub struct Runner<'a> { mac_subsystem: Mac, - pub(crate) rx_channel: Channel, 1>, + pub(crate) rx_channel: Channel, 1>, pub(crate) tx_channel: Channel, pub(crate) tx_buf_channel: Channel, } @@ -36,7 +36,7 @@ impl<'a> Runner<'a> { async { loop { if let Ok(mac_event) = self.mac_subsystem.read().await { - match *mac_event { + match mac_event { MacEvent::McpsDataInd(_) => { self.rx_channel.send(mac_event).await; } diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs index 5ecbfe8c..b0cf0248 100644 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ b/embassy-stm32-wpan/src/sub/mac.rs @@ -12,7 +12,7 @@ use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::{EvtBox, EvtPacket}; use crate::mac::commands::MacCommand; -use crate::mac::event::Event; +use crate::mac::event::MacEvent; use crate::mac::typedefs::MacError; use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; use crate::{channels, evt}; @@ -94,14 +94,16 @@ impl Mac { } } - pub async fn read(&self) -> Result, ()> { - Event::new(self.tl_read().await) + pub async fn read(&self) -> Result, ()> { + MacEvent::new(self.tl_read().await) } } impl evt::MemoryManager for Mac { /// SAFETY: passing a pointer to something other than a managed event packet is UB unsafe fn drop_event_packet(_: *mut EvtPacket) { + trace!("mac drop event"); + // Write the ack CmdPacket::write_into( MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _, @@ -111,7 +113,7 @@ impl evt::MemoryManager for Mac { ); // Clear the rx flag - let _ = poll_once(Ipcc::receive::( + let _ = poll_once(Ipcc::receive::<()>( channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, || None, )); diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 7de30778..1379ac6b 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -73,10 +73,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("setting extended address"); let extended_address: u64 = 0xACDE480000000001; @@ -87,10 +84,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("setting short address"); let short_address: u16 = 0x1122; @@ -101,10 +95,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("setting association permit"); let association_permit: bool = true; @@ -115,10 +106,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("setting TX power"); let transmit_power: i8 = 2; @@ -129,10 +117,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("starting FFD device"); mbox.mac_subsystem @@ -147,10 +132,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("setting RX on when idle"); let rx_on_while_idle: bool = true; @@ -161,18 +143,15 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); loop { let evt = mbox.mac_subsystem.read().await; if let Ok(evt) = evt { defmt::info!("parsed mac event"); - defmt::info!("{:#x}", *evt); + defmt::info!("{:#x}", evt); - match *evt { + match evt { MacEvent::MlmeAssociateInd(association) => mbox .mac_subsystem .send_command(&AssociateResponse { diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs index a55b1fc7..bbcd0a70 100644 --- a/examples/stm32wb/src/bin/mac_ffd_net.rs +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs @@ -79,10 +79,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("setting extended address"); let extended_address: u64 = 0xACDE480000000001; @@ -93,10 +90,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("setting short address"); let short_address: u16 = 0x1122; @@ -107,10 +101,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("setting association permit"); let association_permit: bool = true; @@ -121,10 +112,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("setting TX power"); let transmit_power: i8 = 2; @@ -135,10 +123,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("starting FFD device"); mbox.mac_subsystem @@ -153,10 +138,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("setting RX on when idle"); let rx_on_while_idle: bool = true; @@ -167,10 +149,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); let tx_queue = [ make_static!([0u8; 127]), diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index d1307a84..4d8b6601 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -75,10 +75,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("setting extended address"); let extended_address: u64 = 0xACDE480000000002; @@ -89,10 +86,7 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - { - let evt = mbox.mac_subsystem.read().await.unwrap(); - defmt::info!("{:#x}", *evt); - } + defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); info!("getting extended address"); mbox.mac_subsystem @@ -105,9 +99,9 @@ async fn main(spawner: Spawner) { { let evt = mbox.mac_subsystem.read().await.unwrap(); - info!("{:#x}", *evt); + info!("{:#x}", evt); - if let MacEvent::MlmeGetCnf(evt) = *evt { + if let MacEvent::MlmeGetCnf(evt) = evt { if evt.pib_attribute_value_len == 8 { let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; @@ -133,9 +127,9 @@ async fn main(spawner: Spawner) { mbox.mac_subsystem.send_command(&a).await.unwrap(); let short_addr = { let evt = mbox.mac_subsystem.read().await.unwrap(); - info!("{:#x}", *evt); + info!("{:#x}", evt); - if let MacEvent::MlmeAssociateCnf(conf) = *evt { + if let MacEvent::MlmeAssociateCnf(conf) = evt { conf.assoc_short_address } else { defmt::panic!() @@ -152,7 +146,7 @@ async fn main(spawner: Spawner) { .unwrap(); { let evt = mbox.mac_subsystem.read().await.unwrap(); - info!("{:#x}", *evt); + info!("{:#x}", evt); } info!("sending data"); @@ -176,12 +170,12 @@ async fn main(spawner: Spawner) { .unwrap(); { let evt = mbox.mac_subsystem.read().await.unwrap(); - info!("{:#x}", *evt); + info!("{:#x}", evt); } loop { match mbox.mac_subsystem.read().await { - Ok(evt) => info!("{:#x}", *evt), + Ok(evt) => info!("{:#x}", evt), _ => continue, }; } diff --git a/tests/stm32/src/bin/wpan_mac.rs b/tests/stm32/src/bin/wpan_mac.rs index 2b0d67bb..b04a19ee 100644 --- a/tests/stm32/src/bin/wpan_mac.rs +++ b/tests/stm32/src/bin/wpan_mac.rs @@ -57,7 +57,7 @@ async fn main(spawner: Spawner) { .unwrap(); { let evt = mbox.mac_subsystem.read().await.unwrap(); - info!("{:#x}", *evt); + info!("{:#x}", evt); } info!("setting extended address"); @@ -71,7 +71,7 @@ async fn main(spawner: Spawner) { .unwrap(); { let evt = mbox.mac_subsystem.read().await.unwrap(); - info!("{:#x}", *evt); + info!("{:#x}", evt); } info!("getting extended address"); @@ -85,9 +85,9 @@ async fn main(spawner: Spawner) { { let evt = mbox.mac_subsystem.read().await.unwrap(); - info!("{:#x}", *evt); + info!("{:#x}", evt); - if let MacEvent::MlmeGetCnf(evt) = *evt { + if let MacEvent::MlmeGetCnf(evt) = evt { if evt.pib_attribute_value_len == 8 { let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; @@ -111,18 +111,13 @@ async fn main(spawner: Spawner) { }; info!("{}", a); mbox.mac_subsystem.send_command(&a).await.unwrap(); - let short_addr = { - let evt = mbox.mac_subsystem.read().await.unwrap(); - info!("{:#x}", *evt); - - if let MacEvent::MlmeAssociateCnf(conf) = *evt { - conf.assoc_short_address - } else { - defmt::panic!() - } + let short_addr = if let MacEvent::MlmeAssociateCnf(conf) = mbox.mac_subsystem.read().await.unwrap() { + conf.assoc_short_address + } else { + defmt::panic!() }; - _ = short_addr; + info!("{}", short_addr); info!("Test OK"); cortex_m::asm::bkpt(); From 83ff626c4745d73def4e0cf88ea64c21a19d6d1f Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 20 Jul 2023 17:00:03 -0500 Subject: [PATCH 139/148] wpan/mac: incr. runner msdu handle --- embassy-stm32-wpan/src/mac/runner.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index a0090012..007544c6 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -46,6 +46,8 @@ impl<'a> Runner<'a> { } }, async { + let mut msdu_handle = 0x02; + loop { let (buf, len) = self.tx_channel.recv().await; @@ -56,7 +58,7 @@ impl<'a> Runner<'a> { dst_addr_mode: AddressMode::Short, dst_pan_id: PanId([0x1A, 0xAA]), dst_address: MacAddress::BROADCAST, - msdu_handle: 0x02, + msdu_handle: msdu_handle, ack_tx: 0x00, gts_tx: false, security_level: SecurityLevel::Unsecure, @@ -67,6 +69,8 @@ impl<'a> Runner<'a> { .await .unwrap(); + msdu_handle += 1; + // The tx channel should always be of equal capacity to the tx_buf channel self.tx_buf_channel.try_send(buf).unwrap(); } From c80c232a72a561c3d89c8292437996bc07bfb689 Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 20 Jul 2023 19:52:36 -0500 Subject: [PATCH 140/148] wpan: impl. debug for structs --- embassy-stm32-wpan/src/mac/event.rs | 1 + embassy-stm32-wpan/src/mac/indications.rs | 10 +++++++ embassy-stm32-wpan/src/mac/responses.rs | 15 +++++++++++ embassy-stm32-wpan/src/mac/typedefs.rs | 32 +++++++++++++++++------ 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs index b6f57fda..8415bc11 100644 --- a/embassy-stm32-wpan/src/mac/event.rs +++ b/embassy-stm32-wpan/src/mac/event.rs @@ -23,6 +23,7 @@ pub(crate) trait ParseableMacEvent: Sized { } #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[derive(Debug)] pub enum MacEvent<'a> { MlmeAssociateCnf(&'a AssociateConfirm), MlmeDisassociateCnf(&'a DisassociateConfirm), diff --git a/embassy-stm32-wpan/src/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs index 4349af9c..c0b86d74 100644 --- a/embassy-stm32-wpan/src/mac/indications.rs +++ b/embassy-stm32-wpan/src/mac/indications.rs @@ -10,6 +10,7 @@ use super::typedefs::{ /// MLME ASSOCIATE Indication which will be used by the MAC /// to indicate the reception of an association request command #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateIndication { /// Extended address of the device requesting association @@ -31,6 +32,7 @@ impl ParseableMacEvent for AssociateIndication {} /// MLME DISASSOCIATE indication which will be used to send /// disassociation indication to the application. #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DisassociateIndication { /// Extended address of the device requesting association @@ -52,6 +54,7 @@ impl ParseableMacEvent for DisassociateIndication {} /// MLME BEACON NOTIIFY Indication which is used to send parameters contained /// within a beacon frame received by the MAC to the application #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct BeaconNotifyIndication { /// he set of octets comprising the beacon payload to be transferred @@ -73,6 +76,7 @@ impl ParseableMacEvent for BeaconNotifyIndication {} /// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CommStatusIndication { /// The 16-bit PAN identifier of the device from which the frame @@ -103,6 +107,7 @@ impl ParseableMacEvent for CommStatusIndication {} /// MLME GTS Indication indicates that a GTS has been allocated or that a /// previously allocated GTS has been deallocated #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsIndication { /// The short address of the device that has been allocated or deallocated a GTS @@ -126,6 +131,7 @@ impl ParseableMacEvent for GtsIndication {} /// MLME ORPHAN Indication which is used by the coordinator to notify the /// application of the presence of an orphaned device #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct OrphanIndication { /// Extended address of the orphaned device @@ -147,6 +153,7 @@ impl ParseableMacEvent for OrphanIndication {} /// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss /// of synchronization with the coordinator #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SyncLossIndication { /// The PAN identifier with which the device lost synchronization or to which it was realigned @@ -172,6 +179,7 @@ impl ParseableMacEvent for SyncLossIndication {} /// MLME DPS Indication which indicates the expiration of the DPSIndexDuration /// and the resetting of the DPS values in the PHY #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DpsIndication { /// byte stuffing to keep 32 bit alignment @@ -181,6 +189,7 @@ pub struct DpsIndication { impl ParseableMacEvent for DpsIndication {} #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DataIndication { /// Pointer to the set of octets forming the MSDU being indicated @@ -244,6 +253,7 @@ impl DataIndication { /// MLME POLL Indication which will be used for indicating the Data Request /// reception to upper layer as defined in Zigbee r22 - D.8.2 #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PollIndication { /// addressing mode used diff --git a/embassy-stm32-wpan/src/mac/responses.rs b/embassy-stm32-wpan/src/mac/responses.rs index 5d203084..9c407a36 100644 --- a/embassy-stm32-wpan/src/mac/responses.rs +++ b/embassy-stm32-wpan/src/mac/responses.rs @@ -8,6 +8,7 @@ use super::typedefs::{ /// MLME ASSOCIATE Confirm used to inform of the initiating device whether /// its request to associate was successful or unsuccessful #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateConfirm { /// short address allocated by the coordinator on successful association @@ -30,6 +31,7 @@ impl ParseableMacEvent for AssociateConfirm {} /// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application. #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DisassociateConfirm { /// status of the disassociation attempt @@ -46,6 +48,7 @@ impl ParseableMacEvent for DisassociateConfirm {} /// MLME GET Confirm which requests information about a given PIB attribute #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GetConfirm { /// The pointer to the value of the PIB attribute attempted to read @@ -65,6 +68,7 @@ impl ParseableMacEvent for GetConfirm {} /// MLME GTS Confirm which eports the results of a request to allocate a new GTS /// or to deallocate an existing GTS #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsConfirm { /// The characteristics of the GTS @@ -79,6 +83,7 @@ impl ParseableMacEvent for GtsConfirm {} /// MLME RESET Confirm which is used to report the results of the reset operation #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ResetConfirm { /// The result of the reset operation @@ -92,6 +97,7 @@ impl ParseableMacEvent for ResetConfirm {} /// MLME RX ENABLE Confirm which is used to report the results of the attempt /// to enable or disable the receiver #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct RxEnableConfirm { /// Result of the request to enable or disable the receiver @@ -104,6 +110,7 @@ impl ParseableMacEvent for RxEnableConfirm {} /// MLME SCAN Confirm which is used to report the result of the channel scan request #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ScanConfirm { /// Status of the scan request @@ -130,6 +137,7 @@ impl ParseableMacEvent for ScanConfirm {} /// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SetConfirm { /// The result of the set operation @@ -145,6 +153,7 @@ impl ParseableMacEvent for SetConfirm {} /// MLME START Confirm which is used to report the results of the attempt to /// start using a new superframe configuration #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct StartConfirm { /// Result of the attempt to start using an updated superframe configuration @@ -157,6 +166,7 @@ impl ParseableMacEvent for StartConfirm {} /// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PollConfirm { /// The status of the data request @@ -169,6 +179,7 @@ impl ParseableMacEvent for PollConfirm {} /// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DpsConfirm { /// The status of the DPS request @@ -182,6 +193,7 @@ impl ParseableMacEvent for DpsConfirm {} /// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide /// channel sounding information #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SoundingConfirm { /// Results of the sounding measurement @@ -195,6 +207,7 @@ impl ParseableMacEvent for SoundingConfirm {} /// MLME CALIBRATE Confirm which reports the result of a request to the PHY /// to provide internal propagation path information #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CalibrateConfirm { /// The status of the attempt to return sounding data @@ -214,6 +227,7 @@ impl ParseableMacEvent for CalibrateConfirm {} /// MCPS DATA Confirm which will be used for reporting the results of /// MAC data related requests from the application #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DataConfirm { /// The handle associated with the MSDU being confirmed @@ -245,6 +259,7 @@ impl ParseableMacEvent for DataConfirm {} /// MCPS PURGE Confirm which will be used by the MAC to notify the application of /// the status of its request to purge an MSDU from the transaction queue #[repr(C)] +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PurgeConfirm { /// Handle associated with the MSDU requested to be purged from the transaction queue diff --git a/embassy-stm32-wpan/src/mac/typedefs.rs b/embassy-stm32-wpan/src/mac/typedefs.rs index 98c67c86..0552b8ea 100644 --- a/embassy-stm32-wpan/src/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/mac/typedefs.rs @@ -1,3 +1,5 @@ +use core::fmt::Debug; + use crate::numeric_enum; #[derive(Debug)] @@ -37,7 +39,7 @@ numeric_enum! { numeric_enum! { #[repr(u8)] /// this enum contains all the MAC PIB Ids - #[derive(Default)] + #[derive(Default, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum PibId { // PHY @@ -96,7 +98,7 @@ numeric_enum! { numeric_enum! { #[repr(u8)] - #[derive(Default, Clone, Copy)] + #[derive(Default, Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AddressMode { #[default] @@ -113,6 +115,18 @@ pub union MacAddress { pub extended: [u8; 8], } +impl Debug for MacAddress { + fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + unsafe { + write!( + fmt, + "MacAddress {{ short: {:?}, extended: {:?} }}", + self.short, self.extended + ) + } + } +} + #[cfg(feature = "defmt")] impl defmt::Format for MacAddress { fn format(&self, fmt: defmt::Formatter) { @@ -159,7 +173,7 @@ pub struct GtsCharacteristics { /// MAC PAN Descriptor which contains the network details of the device from /// which the beacon is received -#[derive(Default, Clone, Copy)] +#[derive(Default, Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PanDescriptor { /// PAN identifier of the coordinator @@ -223,7 +237,7 @@ impl TryFrom<&[u8]> for PanDescriptor { numeric_enum! { #[repr(u8)] - #[derive(Default, Clone, Copy)] + #[derive(Default, Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] /// Building wireless applications with STM32WB series MCUs - Application note 13.10.3 pub enum MacChannel { @@ -289,7 +303,7 @@ defmt::bitflags! { numeric_enum! { #[repr(u8)] - #[derive(Default, Clone, Copy)] + #[derive(Default, Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum KeyIdMode { #[default] @@ -306,6 +320,7 @@ numeric_enum! { numeric_enum! { #[repr(u8)] + #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AssociationStatus { /// Association successful @@ -319,7 +334,7 @@ numeric_enum! { numeric_enum! { #[repr(u8)] - #[derive(Clone, Copy)] + #[derive(Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DisassociationReason { /// The coordinator wishes the device to leave the PAN. @@ -331,7 +346,7 @@ numeric_enum! { numeric_enum! { #[repr(u8)] - #[derive(Default, Clone, Copy)] + #[derive(Default, Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SecurityLevel { /// MAC Unsecured Mode Security @@ -346,6 +361,7 @@ numeric_enum! { numeric_enum! { #[repr(u8)] + #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ScanType { EdScan = 0x00, @@ -356,7 +372,7 @@ numeric_enum! { } /// newtype for Pan Id -#[derive(Default, Clone, Copy)] +#[derive(Default, Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PanId(pub [u8; 2]); From 899a68325c322a813155c7ba9c6e43c79be99bd8 Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 20 Jul 2023 20:51:49 -0500 Subject: [PATCH 141/148] wpan: impl. draft control scheme --- embassy-stm32-wpan/src/mac/control.rs | 86 ++++++++++++++++++++++++--- embassy-stm32-wpan/src/mac/event.rs | 2 + embassy-stm32-wpan/src/mac/mod.rs | 2 +- embassy-stm32-wpan/src/mac/runner.rs | 31 +++++++++- 4 files changed, 109 insertions(+), 12 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs index c45f6407..fd8c22b2 100644 --- a/embassy-stm32-wpan/src/mac/control.rs +++ b/embassy-stm32-wpan/src/mac/control.rs @@ -1,12 +1,16 @@ +use core::future::Future; +use core::task; + +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::mutex::MutexGuard; +use embassy_sync::signal::Signal; +use futures::FutureExt; + +use super::commands::MacCommand; +use super::typedefs::MacError; use crate::mac::runner::Runner; -#[derive(Debug)] -pub struct Error { - pub status: u32, -} - pub struct Control<'a> { - #[allow(dead_code)] runner: &'a Runner<'a>, } @@ -15,7 +19,73 @@ impl<'a> Control<'a> { Self { runner: runner } } - pub async fn init(&mut self) { - // TODO + pub async fn send_command(&self, cmd: &T) -> Result<(), MacError> + where + T: MacCommand, + { + let _wm = self.runner.write_mutex.lock().await; + + self.runner.mac_subsystem.send_command(cmd).await + } + + pub async fn send_command_and_get_response(&self, cmd: &T) -> Result, MacError> + where + T: MacCommand, + { + let _wm = self.runner.write_mutex.lock().await; + let rm = self.runner.read_mutex.lock().await; + let token = EventToken::new(self.runner, rm); + + self.runner.mac_subsystem.send_command(cmd).await?; + + Ok(token) + } +} + +pub struct EventToken<'a> { + runner: &'a Runner<'a>, + _mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>, +} + +impl<'a> EventToken<'a> { + pub(crate) fn new(runner: &'a Runner<'a>, mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>) -> Self { + // Enable event receiving + runner.rx_event_channel.lock(|s| { + *s.borrow_mut() = Some(Signal::new()); + }); + + Self { + runner: runner, + _mutex_guard: mutex_guard, + } + } +} + +impl<'a> Future for EventToken<'a> { + // TODO: output something + type Output = (); + + fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll { + self.get_mut().runner.rx_event_channel.lock(|s| { + let signal = s.borrow_mut(); + let signal = match &*signal { + Some(s) => s, + _ => unreachable!(), + }; + + let _ = signal.wait().poll_unpin(cx); + }); + + todo!() + } +} + +impl<'a> Drop for EventToken<'a> { + fn drop(&mut self) { + // Disable event receiving + // This will also drop the contained event, if it exists, and will free up receiving the next event + self.runner.rx_event_channel.lock(|s| { + *s.borrow_mut() = None; + }); } } diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs index 8415bc11..9ca4f5a2 100644 --- a/embassy-stm32-wpan/src/mac/event.rs +++ b/embassy-stm32-wpan/src/mac/event.rs @@ -144,6 +144,8 @@ impl<'a> MacEvent<'a> { } } +unsafe impl<'a> Send for MacEvent<'a> {} + impl<'a> Drop for MacEvent<'a> { fn drop(&mut self) { unsafe { mac::Mac::drop_event_packet(ptr::null_mut()) }; diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs index a93f7a69..c847a5cc 100644 --- a/embassy-stm32-wpan/src/mac/mod.rs +++ b/embassy-stm32-wpan/src/mac/mod.rs @@ -10,7 +10,7 @@ pub mod responses; pub mod runner; pub mod typedefs; -pub use crate::mac::control::{Control, Error as ControlError}; +pub use crate::mac::control::Control; use crate::mac::driver::Driver; pub use crate::mac::runner::Runner; diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index 007544c6..f964d6b3 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -1,6 +1,11 @@ +use core::cell::RefCell; + use embassy_futures::join; -use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::blocking_mutex; +use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; use embassy_sync::channel::Channel; +use embassy_sync::mutex::Mutex; +use embassy_sync::signal::Signal; use crate::mac::commands::DataRequest; use crate::mac::event::MacEvent; @@ -9,7 +14,13 @@ use crate::mac::MTU; use crate::sub::mac::Mac; pub struct Runner<'a> { - mac_subsystem: Mac, + pub(crate) mac_subsystem: Mac, + + // rx event backpressure is already provided through the MacEvent drop mechanism + pub(crate) rx_event_channel: + blocking_mutex::Mutex>>>>, + pub(crate) read_mutex: Mutex, + pub(crate) write_mutex: Mutex, pub(crate) rx_channel: Channel, 1>, pub(crate) tx_channel: Channel, pub(crate) tx_buf_channel: Channel, @@ -19,6 +30,9 @@ impl<'a> Runner<'a> { pub fn new(mac: Mac, tx_buf_queue: [&'a mut [u8; MTU]; 5]) -> Self { let this = Self { mac_subsystem: mac, + rx_event_channel: blocking_mutex::Mutex::new(RefCell::new(None)), + read_mutex: Mutex::new(()), + write_mutex: Mutex::new(()), rx_channel: Channel::new(), tx_channel: Channel::new(), tx_buf_channel: Channel::new(), @@ -40,7 +54,16 @@ impl<'a> Runner<'a> { MacEvent::McpsDataInd(_) => { self.rx_channel.send(mac_event).await; } - _ => {} + _ => { + self.rx_event_channel.lock(|s| { + match &*s.borrow() { + Some(signal) => { + signal.signal(mac_event); + } + None => {} + }; + }); + } } } } @@ -50,7 +73,9 @@ impl<'a> Runner<'a> { loop { let (buf, len) = self.tx_channel.recv().await; + let _wm = self.write_mutex.lock().await; + // The mutex should be dropped on the next loop iteration self.mac_subsystem .send_command( DataRequest { From c675208b8a90bee39e99c8cd3bb620b99c439482 Mon Sep 17 00:00:00 2001 From: xoviat Date: Fri, 21 Jul 2023 16:10:34 -0500 Subject: [PATCH 142/148] wpan: complete prelim. command impl. --- embassy-stm32-wpan/src/mac/control.rs | 16 ++++++++++------ embassy-stm32-wpan/src/mac/runner.rs | 7 ++++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs index fd8c22b2..ded41920 100644 --- a/embassy-stm32-wpan/src/mac/control.rs +++ b/embassy-stm32-wpan/src/mac/control.rs @@ -1,5 +1,6 @@ use core::future::Future; use core::task; +use core::task::Poll; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::mutex::MutexGuard; @@ -7,6 +8,7 @@ use embassy_sync::signal::Signal; use futures::FutureExt; use super::commands::MacCommand; +use super::event::MacEvent; use super::typedefs::MacError; use crate::mac::runner::Runner; @@ -62,10 +64,9 @@ impl<'a> EventToken<'a> { } impl<'a> Future for EventToken<'a> { - // TODO: output something - type Output = (); + type Output = MacEvent<'a>; - fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll { + fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll { self.get_mut().runner.rx_event_channel.lock(|s| { let signal = s.borrow_mut(); let signal = match &*signal { @@ -73,10 +74,13 @@ impl<'a> Future for EventToken<'a> { _ => unreachable!(), }; - let _ = signal.wait().poll_unpin(cx); - }); + let result = match signal.wait().poll_unpin(cx) { + Poll::Ready(mac_event) => Poll::Ready(mac_event), + Poll::Pending => Poll::Pending, + }; - todo!() + result + }) } } diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index f964d6b3..482321b9 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -13,12 +13,13 @@ use crate::mac::typedefs::{AddressMode, MacAddress, PanId, SecurityLevel}; use crate::mac::MTU; use crate::sub::mac::Mac; +type ZeroCopyPubSub = blocking_mutex::Mutex>>>; + pub struct Runner<'a> { pub(crate) mac_subsystem: Mac, - // rx event backpressure is already provided through the MacEvent drop mechanism - pub(crate) rx_event_channel: - blocking_mutex::Mutex>>>>, + // therefore, we don't need to worry about overwriting events + pub(crate) rx_event_channel: ZeroCopyPubSub>, pub(crate) read_mutex: Mutex, pub(crate) write_mutex: Mutex, pub(crate) rx_channel: Channel, 1>, From f4d6a23f92c8f6d3eb97a09e5bc51bac5e8d6837 Mon Sep 17 00:00:00 2001 From: xoviat Date: Fri, 21 Jul 2023 17:02:36 -0500 Subject: [PATCH 143/148] wpan/mac: misc fixes --- embassy-stm32-wpan/src/mac/control.rs | 2 +- embassy-stm32-wpan/src/mac/responses.rs | 6 +++--- embassy-stm32-wpan/src/mac/runner.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs index ded41920..8a13de81 100644 --- a/embassy-stm32-wpan/src/mac/control.rs +++ b/embassy-stm32-wpan/src/mac/control.rs @@ -34,8 +34,8 @@ impl<'a> Control<'a> { where T: MacCommand, { - let _wm = self.runner.write_mutex.lock().await; let rm = self.runner.read_mutex.lock().await; + let _wm = self.runner.write_mutex.lock().await; let token = EventToken::new(self.runner, rm); self.runner.mac_subsystem.send_command(cmd).await?; diff --git a/embassy-stm32-wpan/src/mac/responses.rs b/embassy-stm32-wpan/src/mac/responses.rs index 9c407a36..544fdaae 100644 --- a/embassy-stm32-wpan/src/mac/responses.rs +++ b/embassy-stm32-wpan/src/mac/responses.rs @@ -87,7 +87,7 @@ impl ParseableMacEvent for GtsConfirm {} #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ResetConfirm { /// The result of the reset operation - status: MacStatus, + pub status: MacStatus, /// byte stuffing to keep 32 bit alignment a_stuffing: [u8; 3], } @@ -101,7 +101,7 @@ impl ParseableMacEvent for ResetConfirm {} #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct RxEnableConfirm { /// Result of the request to enable or disable the receiver - status: MacStatus, + pub status: MacStatus, /// byte stuffing to keep 32 bit alignment a_stuffing: [u8; 3], } @@ -197,7 +197,7 @@ impl ParseableMacEvent for DpsConfirm {} #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SoundingConfirm { /// Results of the sounding measurement - sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED], + pub sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED], status: u8, } diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index 482321b9..1be6df8a 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -95,7 +95,7 @@ impl<'a> Runner<'a> { .await .unwrap(); - msdu_handle += 1; + msdu_handle = msdu_handle.wrapping_add(1); // The tx channel should always be of equal capacity to the tx_buf channel self.tx_buf_channel.try_send(buf).unwrap(); From 19c6c698b54514aff1fc2ad22953a5d63b6193ee Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 22 Jul 2023 11:43:14 -0500 Subject: [PATCH 144/148] stm32: update metapac --- embassy-stm32/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index ec934e8b..0fb6fdb5 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -57,7 +57,7 @@ sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" atomic-polyfill = "1.0.1" -stm32-metapac = "12" +stm32-metapac = "13" vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -74,7 +74,7 @@ critical-section = { version = "1.1", features = ["std"] } [build-dependencies] proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { version = "12", default-features = false, features = ["metadata"]} +stm32-metapac = { version = "13", default-features = false, features = ["metadata"]} [features] default = ["rt"] From 5693ed1178bf77fc131749b65d27bbaf3b3cf3fd Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 22 Jul 2023 11:50:30 -0500 Subject: [PATCH 145/148] stm32: add minimal fdcan impl --- embassy-stm32/src/can/fdcan.rs | 66 ++++++++++++++++++++++++++++++++++ embassy-stm32/src/can/mod.rs | 1 + 2 files changed, 67 insertions(+) create mode 100644 embassy-stm32/src/can/fdcan.rs diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs new file mode 100644 index 00000000..c31a7fc6 --- /dev/null +++ b/embassy-stm32/src/can/fdcan.rs @@ -0,0 +1,66 @@ +pub use bxcan; +use embassy_hal_common::PeripheralRef; + +use crate::peripherals; + +pub(crate) mod sealed { + use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; + use embassy_sync::channel::Channel; + use embassy_sync::waitqueue::AtomicWaker; + + pub struct State { + pub tx_waker: AtomicWaker, + pub err_waker: AtomicWaker, + pub rx_queue: Channel, + } + + impl State { + pub const fn new() -> Self { + Self { + tx_waker: AtomicWaker::new(), + err_waker: AtomicWaker::new(), + rx_queue: Channel::new(), + } + } + } + + pub trait Instance { + const REGISTERS: *mut bxcan::RegisterBlock; + + fn regs() -> &'static crate::pac::can::Fdcan; + fn state() -> &'static State; + } +} + +pub trait InterruptableInstance {} +pub trait Instance: sealed::Instance + InterruptableInstance + 'static {} + +pub struct BxcanInstance<'a, T>(PeripheralRef<'a, T>); + +unsafe impl<'d, T: Instance> bxcan::Instance for BxcanInstance<'d, T> { + const REGISTERS: *mut bxcan::RegisterBlock = T::REGISTERS; +} + +foreach_peripheral!( + (can, $inst:ident) => { + impl sealed::Instance for peripherals::$inst { + const REGISTERS: *mut bxcan::RegisterBlock = crate::pac::$inst.as_ptr() as *mut _; + + fn regs() -> &'static crate::pac::can::Fdcan { + &crate::pac::$inst + } + + fn state() -> &'static sealed::State { + static STATE: sealed::State = sealed::State::new(); + &STATE + } + } + + impl Instance for peripherals::$inst {} + + impl InterruptableInstance for peripherals::$inst {} + }; +); + +pin_trait!(RxPin, Instance); +pin_trait!(TxPin, Instance); diff --git a/embassy-stm32/src/can/mod.rs b/embassy-stm32/src/can/mod.rs index c7e2e620..4ff5aa0d 100644 --- a/embassy-stm32/src/can/mod.rs +++ b/embassy-stm32/src/can/mod.rs @@ -1,5 +1,6 @@ #![macro_use] #[cfg_attr(can_bxcan, path = "bxcan.rs")] +#[cfg_attr(can_fdcan, path = "fdcan.rs")] mod _version; pub use _version::*; From 64f8a779ca4453a40f07433c0bb1ebcaeeeba74c Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 22 Jul 2023 11:54:54 -0500 Subject: [PATCH 146/148] stm32: add dac fix --- embassy-stm32/src/dac/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 31a2d886..3d58914b 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs @@ -51,7 +51,10 @@ impl Ch1Trigger { fn tsel(&self) -> dac::vals::Tsel1 { match self { Ch1Trigger::Tim6 => dac::vals::Tsel1::TIM6_TRGO, + #[cfg(not(dac_v3))] Ch1Trigger::Tim3 => dac::vals::Tsel1::TIM3_TRGO, + #[cfg(dac_v3)] + Ch1Trigger::Tim3 => dac::vals::Tsel1::TIM1_TRGO, Ch1Trigger::Tim7 => dac::vals::Tsel1::TIM7_TRGO, Ch1Trigger::Tim15 => dac::vals::Tsel1::TIM15_TRGO, Ch1Trigger::Tim2 => dac::vals::Tsel1::TIM2_TRGO, From 192cdc2f858b8c8ded7fb50338e2045e784951e3 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 22 Jul 2023 12:07:02 -0500 Subject: [PATCH 147/148] stm32: suppress adc f3 --- embassy-stm32/src/adc/mod.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index 56ecd63c..94a8538b 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -1,5 +1,6 @@ #![macro_use] +#[cfg(not(adc_f3))] #[cfg_attr(adc_f1, path = "f1.rs")] #[cfg_attr(adc_v1, path = "v1.rs")] #[cfg_attr(adc_v2, path = "v2.rs")] @@ -7,14 +8,16 @@ #[cfg_attr(adc_v4, path = "v4.rs")] mod _version; -#[cfg(not(adc_f1))] +#[cfg(not(any(adc_f1, adc_f3)))] mod resolution; mod sample_time; +#[cfg(not(adc_f3))] #[allow(unused)] pub use _version::*; -#[cfg(not(adc_f1))] +#[cfg(not(any(adc_f1, adc_f3)))] pub use resolution::Resolution; +#[cfg(not(adc_f3))] pub use sample_time::SampleTime; use crate::peripherals; @@ -22,13 +25,14 @@ use crate::peripherals; pub struct Adc<'d, T: Instance> { #[allow(unused)] adc: crate::PeripheralRef<'d, T>, + #[cfg(not(adc_f3))] sample_time: SampleTime, } pub(crate) mod sealed { pub trait Instance { fn regs() -> crate::pac::adc::Adc; - #[cfg(all(not(adc_f1), not(adc_v1)))] + #[cfg(not(any(adc_f1, adc_v1, adc_f3)))] fn common_regs() -> crate::pac::adccommon::AdcCommon; } @@ -56,7 +60,7 @@ foreach_peripheral!( fn regs() -> crate::pac::adc::Adc { crate::pac::$inst } - #[cfg(all(not(adc_f1), not(adc_v1)))] + #[cfg(not(any(adc_f1, adc_v1, adc_f3)))] fn common_regs() -> crate::pac::adccommon::AdcCommon { foreach_peripheral!{ (adccommon, $common_inst:ident) => { From ba8e5d8589efda450bf118051be097f320b40ff3 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 22 Jul 2023 12:10:50 -0500 Subject: [PATCH 148/148] rustfmt --- embassy-stm32/src/adc/sample_time.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/adc/sample_time.rs b/embassy-stm32/src/adc/sample_time.rs index 0faa1e3c..df052556 100644 --- a/embassy-stm32/src/adc/sample_time.rs +++ b/embassy-stm32/src/adc/sample_time.rs @@ -1,3 +1,4 @@ +#[cfg(not(adc_f3))] macro_rules! impl_sample_time { ($default_doc:expr, $default:ident, ($(($doc:expr, $variant:ident, $pac_variant:ident)),*)) => { #[doc = concat!("ADC sample time\n\nThe default setting is ", $default_doc, " ADC clock cycles.")]