diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1a1b720..3859f49 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -28,3 +28,12 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - run: cargo clippy -- -D warnings + + build-no-std: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + targets: thumbv7em-none-eabihf + - run: cargo build --target thumbv7em-none-eabihf --no-default-features --features defmt-03 diff --git a/Cargo.toml b/Cargo.toml index 666aeca..30351c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] resolver = "3" members = [ - "lr-wpan-rs" + "lr-wpan-rs", + "lr-wpan-rs-dw1000" ] diff --git a/lr-wpan-rs-dw1000/Cargo.toml b/lr-wpan-rs-dw1000/Cargo.toml new file mode 100644 index 0000000..cb4514d --- /dev/null +++ b/lr-wpan-rs-dw1000/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "lr-wpan-rs-dw1000" +version = "0.1.0" +edition = "2021" + +[dependencies] +lr-wpan-rs = { path = "../lr-wpan-rs", default-features = false } +dw1000 = { git = "https://github.com/jkelleyrtp/dw1000-rs", rev = "698987dbfebb2db16bf20c166bf0d75c16f982c1" } +embassy-futures = "0.1.1" +embedded-hal = "1.0.0" +embedded-hal-async = "1.0.0" +micromath = "2.1.0" +nb = "1.1.0" +defmt = { version = "0.3.10", optional = true } + +[features] +defmt-03 = ["dep:defmt"] diff --git a/lr-wpan-rs/src/phy/dw1000.rs b/lr-wpan-rs-dw1000/src/lib.rs similarity index 95% rename from lr-wpan-rs/src/phy/dw1000.rs rename to lr-wpan-rs-dw1000/src/lib.rs index 7aa33a4..8f53a1b 100644 --- a/lr-wpan-rs/src/phy/dw1000.rs +++ b/lr-wpan-rs-dw1000/src/lib.rs @@ -1,3 +1,5 @@ +#![no_std] + use core::fmt::{Debug, Display}; pub use dw1000; @@ -7,12 +9,8 @@ use dw1000::{ use embassy_futures::select::{select, Either}; use embedded_hal::{delay::DelayNs as DelayNsSync, digital::ErrorType, spi::SpiDevice}; use embedded_hal_async::{delay::DelayNs, digital::Wait}; -#[allow(unused_imports)] -use micromath::F32Ext; - -use super::{ModulationType, Phy, ReceivedMessage}; -use crate::{ - phy::SendContinuation, +use lr_wpan_rs::{ + phy::{ModulationType, Phy, ReceivedMessage, SendContinuation}, pib::{ CcaMode, ChannelDescription, NativePrf, PhyPib, PhyPibWrite, TXPowerTolerance, UwbCurrentPulseShape, @@ -20,6 +18,8 @@ use crate::{ time::{Duration, Instant}, ChannelPage, }; +#[allow(unused_imports)] +use micromath::F32Ext; const TIME_CHECK_INTERVAL_MILLIS: u32 = 5000; const TIME_CHECK_MILLIS_PER_DELAY: u32 = 100; @@ -90,7 +90,7 @@ impl DW1000Phy { } } -impl super::Phy for DW1000Phy { +impl Phy for DW1000Phy { type Error = Error; type ProcessingContext = Either, ()>; @@ -108,7 +108,8 @@ impl super::Phy for DW1000Phy super::Phy for DW1000Phy super::Phy for DW1000Phy Result { + async fn get_instant(&mut self) -> Result { let sys_time = match &mut self.dw1000 { DW1000::Empty => return Err(Error::WrongState), DW1000::Ready(dw1000) => dw1000.sys_time()?.value(), @@ -209,11 +210,11 @@ impl super::Phy for DW1000Phy, + send_time: Option, ranging: bool, use_csma: bool, - continuation: super::SendContinuation, - ) -> Result { + continuation: lr_wpan_rs::phy::SendContinuation, + ) -> Result { assert!(!use_csma, "Not supported"); assert!( !matches!(continuation, SendContinuation::WaitForResponse { .. }), @@ -272,7 +273,7 @@ impl super::Phy for DW1000Phy { // No real recovery possible... #[cfg(feature = "defmt-03")] - panic!("Could not finish sending: {}", defmt::Debug2Format(&e)); + defmt::panic!("Could not finish sending: {}", defmt::Debug2Format(&e)); #[cfg(not(feature = "defmt-03"))] panic!("Could not finish sending: {:?}", e); } @@ -285,7 +286,7 @@ impl super::Phy for DW1000Phy Result<(), Self::Error> { @@ -350,7 +351,7 @@ impl super::Phy for DW1000Phy { let timestamp = self.convert_to_mac_time(message.rx_time).await?; - Ok(Some(super::ReceivedMessage { + Ok(Some(lr_wpan_rs::phy::ReceivedMessage { timestamp, data: message.bytes.try_into().unwrap(), lqi: 255, // TODO @@ -379,7 +380,7 @@ impl super::Phy for DW1000Phy( &mut self, - f: impl FnOnce(&mut crate::pib::PhyPibWrite) -> U, + f: impl FnOnce(&mut lr_wpan_rs::pib::PhyPibWrite) -> U, ) -> Result { let old_pib = self.phy_pib.pib_write.clone(); let old_rx_config = self.current_rx_config; @@ -492,7 +493,7 @@ impl super::Phy for DW1000Phy Result<&crate::pib::PhyPib, Self::Error> { + async fn get_phy_pib(&mut self) -> Result<&lr_wpan_rs::pib::PhyPib, Self::Error> { Ok(&self.phy_pib) } } diff --git a/lr-wpan-rs/Cargo.toml b/lr-wpan-rs/Cargo.toml index 557f1c8..b1e888e 100644 --- a/lr-wpan-rs/Cargo.toml +++ b/lr-wpan-rs/Cargo.toml @@ -9,30 +9,28 @@ repository = "https://github.com/tweedegolf/lr-wpan-rs" readme = "README.md" [dependencies] -embassy-futures = { git = "https://github.com/embassy-rs/embassy.git", tag = "embassy-stm32-v0.2.0", default-features = false } -embassy-sync = { git = "https://github.com/embassy-rs/embassy.git", tag = "embassy-stm32-v0.2.0" } +embassy-futures = { version = "0.1.1", default-features = false } +embassy-sync = { version = "0.6.2" } -arrayvec = { version = "0.7.6", default-features = false } critical-section = "1.2.0" maitake-sync = { version = "0.2.1", default-features = false } -dw1000 = { git = "https://github.com/jkelleyrtp/dw1000-rs", rev = "698987dbfebb2db16bf20c166bf0d75c16f982c1" } -embedded-hal = "1.0.0" -embedded-hal-async = "1.0.0" -nb = "1.1.0" -micromath = "2.1.0" rand_core = "0.9.0" -pcap-file = { version = "2.0.0", optional = true } defmt = { version = "0.3.8", optional = true } -log = { version = "0.4.22", optional = true } arraydeque = { version = "0.5.1", default-features = false } byte = "0.2.7" -rand = { version = "0.9.0", optional = true } futures = { version = "0.3.31", default-features = false, features = ["async-await"] } +micromath = "2.1.0" +embedded-hal-async = "1.0.0" heapless = "0.8.0" ccm = { version = "0.4.0", default-features = false } cipher = { version = "0.3.0", default-features = false } + +# test-helpers +pcap-file = { version = "2.0.0", optional = true } +log = { version = "0.4.22", optional = true } tokio = { version = "1.41.0", optional = true, default-features = false, features = ["time", "test-util"] } +rand = { version = "0.9.0", optional = true } [dev-dependencies] test-log = "0.2.16" @@ -47,6 +45,6 @@ default = ["test_helpers"] std = ["critical-section/std"] test_helpers = ["std", "dep:tokio", "log-04", "dep:rand", "dep:pcap-file"] ## Use [`defmt`](https://docs.rs/defmt/latest/defmt/) for logging -defmt-03 = ["dep:defmt"] +defmt-03 = ["dep:defmt", "heapless/defmt-03"] ## Use [`log`](https://docs.rs/log/latest/log/) for logging log-04 = ["dep:log"] diff --git a/lr-wpan-rs/src/mac/mlme_reset.rs b/lr-wpan-rs/src/mac/mlme_reset.rs index 24c9896..727bd08 100644 --- a/lr-wpan-rs/src/mac/mlme_reset.rs +++ b/lr-wpan-rs/src/mac/mlme_reset.rs @@ -1,5 +1,3 @@ -#[allow(unused_imports)] -use micromath::F32Ext; use rand_core::RngCore; use super::{commander::RequestResponder, state::MacState, MacConfig, MacError}; diff --git a/lr-wpan-rs/src/mac/mlme_scan.rs b/lr-wpan-rs/src/mac/mlme_scan.rs index ad4bd37..6e8f7d2 100644 --- a/lr-wpan-rs/src/mac/mlme_scan.rs +++ b/lr-wpan-rs/src/mac/mlme_scan.rs @@ -180,7 +180,10 @@ impl ScanProcess<'_> { } // Push the descriptor - self.results.pan_descriptor_list.push(pan_descriptor); + self.results + .pan_descriptor_list + .push(pan_descriptor) + .unwrap(); self.results.result_list_size += 1; // End the scan if full diff --git a/lr-wpan-rs/src/mac/state.rs b/lr-wpan-rs/src/mac/state.rs index 1a6f15f..8197538 100644 --- a/lr-wpan-rs/src/mac/state.rs +++ b/lr-wpan-rs/src/mac/state.rs @@ -1,5 +1,5 @@ use arraydeque::ArrayDeque; -use arrayvec::ArrayVec; +use heapless::Vec; use rand_core::RngCore; use super::{callback::SendCallback, mlme_scan::ScanProcess, MacConfig}; @@ -57,10 +57,13 @@ impl MacState<'_> { pub fn serialize_frame( &mut self, frame: crate::wire::Frame<'_>, - ) -> ArrayVec { + ) -> Vec { use byte::TryWrite; - let mut buffer = ArrayVec::from([0; crate::consts::MAX_PHY_PACKET_SIZE]); + let mut buffer = Vec::new(); + buffer + .resize_default(crate::consts::MAX_PHY_PACKET_SIZE) + .unwrap(); let length = frame .try_write(&mut buffer, &mut self.frame_ser_des_context()) .expect("Buffer is always big enough"); @@ -107,7 +110,7 @@ pub struct MessageScheduler<'a> { impl<'a> MessageScheduler<'a> { pub fn schedule_broadcast_priority( &mut self, - data: ArrayVec, + data: Vec, callback: SendCallback<'a>, ) { if self @@ -122,7 +125,7 @@ impl<'a> MessageScheduler<'a> { #[expect(dead_code, reason = "for future use")] pub fn schedule_broadcast( &mut self, - data: ArrayVec, + data: Vec, callback: SendCallback<'a>, ) { if self @@ -148,7 +151,7 @@ impl<'a> MessageScheduler<'a> { } pub struct ScheduledMessage<'a> { - pub data: ArrayVec, + pub data: Vec, pub callback: SendCallback<'a>, } diff --git a/lr-wpan-rs/src/phy/mod.rs b/lr-wpan-rs/src/phy.rs similarity index 98% rename from lr-wpan-rs/src/phy/mod.rs rename to lr-wpan-rs/src/phy.rs index 39490fd..6e19b47 100644 --- a/lr-wpan-rs/src/phy/mod.rs +++ b/lr-wpan-rs/src/phy.rs @@ -1,4 +1,4 @@ -use arrayvec::ArrayVec; +use heapless::Vec; use crate::{ pib::{PhyPib, PhyPibWrite}, @@ -6,8 +6,6 @@ use crate::{ ChannelPage, }; -pub mod dw1000; - pub trait Phy { #[cfg(not(feature = "defmt-03"))] type Error: core::error::Error; @@ -111,7 +109,7 @@ pub enum SendContinuation { pub struct ReceivedMessage { /// The time at which the message was received pub timestamp: Instant, - pub data: ArrayVec, + pub data: Vec, /// The LQI at which the network beacon was received. Lower values represent lower LQI, as defined in 8.2.6. pub lqi: u8, /// The channel on which the message was received diff --git a/lr-wpan-rs/src/sap/beacon_notify.rs b/lr-wpan-rs/src/sap/beacon_notify.rs index 4d9ddba..2489571 100644 --- a/lr-wpan-rs/src/sap/beacon_notify.rs +++ b/lr-wpan-rs/src/sap/beacon_notify.rs @@ -1,4 +1,4 @@ -use arrayvec::ArrayVec; +use heapless::Vec; use super::{Indication, IndicationValue, PanDescriptor}; use crate::{consts::MAX_BEACON_PAYLOAD_LENGTH, wire::beacon::PendingAddress}; @@ -16,7 +16,7 @@ pub struct BeaconNotifyIndication { /// The set of octets comprising the beacon /// payload to be transferred from the MAC /// sublayer entity to the next higher layer. - pub sdu: ArrayVec, + pub sdu: Vec, } impl From for BeaconNotifyIndication { diff --git a/lr-wpan-rs/src/sap/data.rs b/lr-wpan-rs/src/sap/data.rs index 1fb35db..af4009a 100644 --- a/lr-wpan-rs/src/sap/data.rs +++ b/lr-wpan-rs/src/sap/data.rs @@ -1,4 +1,4 @@ -use arrayvec::ArrayVec; +use heapless::Vec; use super::{ ConfirmValue, Indication, IndicationValue, Request, RequestValue, SecurityInfo, Status, @@ -49,7 +49,7 @@ pub struct DataRequest { /// The individual device address of the entity to which the MSDU is being transferred. pub dst_addr: Option, /// The set of octets forming the MSDU to be transmitted by the MAC sublayer entity. - pub msdu: ArrayVec, + pub msdu: Vec, /// The handle associated with the MSDU to be transmitted by the MAC sublayer entity. pub msdu_handle: u8, /// TRUE if acknowledged transmission is used, FALSE otherwise. @@ -206,7 +206,7 @@ pub struct DataIndication { /// The individual device address of the entity to which the MSDU is being transferred. pub dst_addr: Option, /// The set of octets forming the MSDU being indicated by the MAC sublayer entity. - pub msdu: ArrayVec, + pub msdu: Vec, /// LQI value measured during reception of the MPDU. /// Lower values represent lower LQI, as described in 8.2.6. pub mpdu_link_quality: u8, diff --git a/lr-wpan-rs/src/sap/scan.rs b/lr-wpan-rs/src/sap/scan.rs index 48db49f..59c8463 100644 --- a/lr-wpan-rs/src/sap/scan.rs +++ b/lr-wpan-rs/src/sap/scan.rs @@ -1,4 +1,4 @@ -use arrayvec::ArrayVec; +use heapless::Vec; use super::{ConfirmValue, PanDescriptor, Request, RequestValue, SecurityInfo, Status}; use crate::ChannelPage; @@ -11,7 +11,7 @@ use crate::ChannelPage; #[derive(Debug, Clone, PartialEq, Eq)] pub struct ScanRequest { pub scan_type: ScanType, - pub scan_channels: ArrayVec, + pub scan_channels: Vec, /// A value used to calculate the length of time to /// spend scanning each channel for ED, active, /// and passive scans. This parameter is ignored for @@ -83,7 +83,7 @@ pub struct ScanConfirm { /// A list of the channels given in the /// request which were not scanned. This /// parameter is not valid for ED scans. - pub unscanned_channels: ArrayVec, + pub unscanned_channels: Vec, /// The number of elements returned in /// the appropriate result lists. This value /// is zero for the result of an orphan scan. @@ -92,14 +92,14 @@ pub struct ScanConfirm { /// for each channel searched during an /// ED scan. This parameter is null for /// active, passive, and orphan scans. - pub energy_detect_list: ArrayVec, + pub energy_detect_list: Vec, /// The list of PAN descriptors, one for /// each beacon found during an active or /// passive scan if macAutoRequest is set /// to TRUE. This parameter is null for /// ED and orphan scans or when macAutoRequest is set to FALSE during an /// active or passive scan. - pub pan_descriptor_list: alloc::boxed::Box>, + pub pan_descriptor_list: alloc::boxed::Box>, /// Categorization of energy detected in /// channel with the following values: /// - 0: Category detection is not supported @@ -113,7 +113,7 @@ pub struct ScanConfirm { /// ResultListSize. This parameter is null /// for active, passive, and orphan scans. It /// is also null for non-UWB PHYs. - pub uwb_energy_detect_list: ArrayVec, + pub uwb_energy_detect_list: Vec, } impl From for ScanConfirm { diff --git a/lr-wpan-rs/src/sap/sounding.rs b/lr-wpan-rs/src/sap/sounding.rs index a583123..e08f090 100644 --- a/lr-wpan-rs/src/sap/sounding.rs +++ b/lr-wpan-rs/src/sap/sounding.rs @@ -1,5 +1,3 @@ -use alloc::vec::Vec; - use super::{ConfirmValue, Request, RequestValue, Status}; /// The MLME-SOUNDING.request primitive is used by the next higher layer to request that the PHY respond @@ -37,7 +35,7 @@ impl Request for SoundingRequest { /// UNSUPPORTED_ATTRIBUTE. #[derive(Debug, Clone, PartialEq, Eq)] pub struct SoundingConfirm { - pub sounding_list: Vec, + pub sounding_list: alloc::vec::Vec, pub status: Status, } diff --git a/lr-wpan-rs/src/test_helpers/aether/mod.rs b/lr-wpan-rs/src/test_helpers/aether/mod.rs index c0f29ae..a6cf4d5 100644 --- a/lr-wpan-rs/src/test_helpers/aether/mod.rs +++ b/lr-wpan-rs/src/test_helpers/aether/mod.rs @@ -47,8 +47,8 @@ use std::{ }, }; -use arrayvec::ArrayVec; use byte::TryRead; +use heapless::Vec; use pcap_file::{ pcapng::{ blocks::{ @@ -324,13 +324,13 @@ pub struct Node { #[derive(Debug, Clone)] pub struct AirPacket { - pub data: ArrayVec, + pub data: Vec, pub time_stamp: Instant, pub channel: u8, } impl AirPacket { - pub fn new(data: impl TryInto>, time_stamp: Instant, channel: u8) -> Self { + pub fn new(data: impl TryInto>, time_stamp: Instant, channel: u8) -> Self { let Ok(data) = data.try_into() else { unreachable!("Test data always fits 127 bytes"); }; @@ -481,7 +481,10 @@ mod tests { let mut alice = a.radio(); let mut bob = a.radio(); - let mut buffer = ArrayVec::from([0; crate::consts::MAX_PHY_PACKET_SIZE]); + let mut buffer = Vec::<_, { crate::consts::MAX_PHY_PACKET_SIZE }>::new(); + buffer + .resize_default(crate::consts::MAX_PHY_PACKET_SIZE) + .unwrap(); let mut ctx = wire::FrameSerDesContext::::new( FooterMode::None, None,