diff options
| author | xoviat <[email protected]> | 2025-11-17 17:27:25 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-11-17 17:27:25 +0000 |
| commit | 45797ecb8501d7a22c53967fad45ee7490424991 (patch) | |
| tree | 6b61248333bbc9f12948ca9689104bc03d592757 | |
| parent | 9cd6c92151e4ee68bca95bfc17658e50ad2c1aca (diff) | |
| parent | ca02cdf792d4aff16e2f265616bec5abdb3c7a1a (diff) | |
Merge pull request #4905 from xoviat/wpan
wpan: get embasy_net actually working parse frames correctly
| -rw-r--r-- | embassy-stm32-wpan/Cargo.toml | 3 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/commands.rs | 26 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/control.rs | 36 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/driver.rs | 24 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/indications.rs | 18 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/runner.rs | 101 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/typedefs.rs | 43 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/sub/mm.rs | 2 | ||||
| -rw-r--r-- | examples/stm32wb/src/bin/mac_ffd_net.rs | 90 |
9 files changed, 259 insertions, 84 deletions
diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 75d978d1a..05d76f4a6 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml | |||
| @@ -33,6 +33,7 @@ embassy-futures = { version = "0.1.2", path = "../embassy-futures" } | |||
| 33 | embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" } | 33 | embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" } |
| 34 | embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal" } | 34 | embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal" } |
| 35 | embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", optional=true } | 35 | embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", optional=true } |
| 36 | smoltcp = { version = "0.12.0", optional=true, default-features = false } | ||
| 36 | 37 | ||
| 37 | defmt = { version = "1.0.1", optional = true } | 38 | defmt = { version = "1.0.1", optional = true } |
| 38 | log = { version = "0.4.17", optional = true } | 39 | log = { version = "0.4.17", optional = true } |
| @@ -52,7 +53,7 @@ bitflags = { version = "2.3.3", optional = true } | |||
| 52 | defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "stm32wb-hci?/defmt"] | 53 | defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "stm32wb-hci?/defmt"] |
| 53 | 54 | ||
| 54 | ble = ["dep:stm32wb-hci"] | 55 | ble = ["dep:stm32wb-hci"] |
| 55 | mac = ["dep:bitflags", "dep:embassy-net-driver" ] | 56 | mac = ["dep:bitflags", "dep:embassy-net-driver", "dep:smoltcp", "smoltcp/medium-ieee802154"] |
| 56 | 57 | ||
| 57 | extended = [] | 58 | extended = [] |
| 58 | 59 | ||
diff --git a/embassy-stm32-wpan/src/mac/commands.rs b/embassy-stm32-wpan/src/mac/commands.rs index 82b9d2772..a3a40f377 100644 --- a/embassy-stm32-wpan/src/mac/commands.rs +++ b/embassy-stm32-wpan/src/mac/commands.rs | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | 2 | ||
| 3 | use core::{mem, slice}; | 3 | use core::{mem, slice}; |
| 4 | 4 | ||
| 5 | use smoltcp::wire::ieee802154::Frame; | ||
| 6 | |||
| 5 | use super::opcodes::OpcodeM4ToM0; | 7 | use super::opcodes::OpcodeM4ToM0; |
| 6 | use super::typedefs::{ | 8 | use super::typedefs::{ |
| 7 | AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, MacStatus, | 9 | AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, MacStatus, |
| @@ -379,6 +381,30 @@ impl DataRequest { | |||
| 379 | } | 381 | } |
| 380 | } | 382 | } |
| 381 | 383 | ||
| 384 | impl<'a, T: AsRef<[u8]>> TryFrom<Frame<&'a T>> for DataRequest { | ||
| 385 | type Error = (); | ||
| 386 | |||
| 387 | fn try_from(frame: Frame<&'a T>) -> Result<Self, Self::Error> { | ||
| 388 | // TODO: map the rest of these | ||
| 389 | |||
| 390 | let mut request = DataRequest { | ||
| 391 | src_addr_mode: frame.src_addressing_mode().try_into()?, | ||
| 392 | dst_addr_mode: frame.dst_addressing_mode().try_into()?, | ||
| 393 | dst_pan_id: frame.dst_pan_id().ok_or(())?.into(), | ||
| 394 | dst_address: frame.dst_addr().ok_or(())?.into(), | ||
| 395 | msdu_handle: frame.sequence_number().ok_or(())?, | ||
| 396 | ack_tx: 0x00, | ||
| 397 | gts_tx: false, | ||
| 398 | security_level: SecurityLevel::Unsecure, | ||
| 399 | ..Default::default() | ||
| 400 | }; | ||
| 401 | |||
| 402 | request.set_buffer(frame.payload().ok_or(())?); | ||
| 403 | |||
| 404 | Ok(request) | ||
| 405 | } | ||
| 406 | } | ||
| 407 | |||
| 382 | impl Default for DataRequest { | 408 | impl Default for DataRequest { |
| 383 | fn default() -> Self { | 409 | fn default() -> Self { |
| 384 | Self { | 410 | Self { |
diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs index 8fb971da3..d2a7b65ee 100644 --- a/embassy-stm32-wpan/src/mac/control.rs +++ b/embassy-stm32-wpan/src/mac/control.rs | |||
| @@ -38,7 +38,7 @@ impl<'a> Control<'a> { | |||
| 38 | } | 38 | } |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | pub async fn init_link(&mut self, short_address: [u8; 2], extended_address: [u8; 8], pan_id: [u8; 2]) { | 41 | pub async fn init_link(&mut self, pan_id: [u8; 2]) { |
| 42 | debug!("resetting"); | 42 | debug!("resetting"); |
| 43 | 43 | ||
| 44 | debug!( | 44 | debug!( |
| @@ -52,12 +52,19 @@ impl<'a> Control<'a> { | |||
| 52 | .await | 52 | .await |
| 53 | ); | 53 | ); |
| 54 | 54 | ||
| 55 | let (short_address, mac_address) = critical_section::with(|cs| { | ||
| 56 | let mut network_state = self.network_state.borrow(cs).borrow_mut(); | ||
| 57 | |||
| 58 | network_state.pan_id = pan_id; | ||
| 59 | |||
| 60 | (network_state.short_addr, network_state.mac_addr) | ||
| 61 | }); | ||
| 62 | |||
| 55 | debug!("setting extended address"); | 63 | debug!("setting extended address"); |
| 56 | let extended_address: u64 = u64::from_be_bytes(extended_address); | ||
| 57 | debug!( | 64 | debug!( |
| 58 | "{:#x}", | 65 | "{:#x}", |
| 59 | self.send_command_and_get_response(&SetRequest { | 66 | self.send_command_and_get_response(&SetRequest { |
| 60 | pib_attribute_ptr: &extended_address as *const _ as *const u8, | 67 | pib_attribute_ptr: &u64::from_be_bytes(mac_address) as *const _ as *const u8, |
| 61 | pib_attribute: PibId::ExtendedAddress, | 68 | pib_attribute: PibId::ExtendedAddress, |
| 62 | }) | 69 | }) |
| 63 | .await | 70 | .await |
| @@ -66,11 +73,10 @@ impl<'a> Control<'a> { | |||
| 66 | ); | 73 | ); |
| 67 | 74 | ||
| 68 | debug!("setting short address"); | 75 | debug!("setting short address"); |
| 69 | let short_address: u16 = u16::from_be_bytes(short_address); | ||
| 70 | debug!( | 76 | debug!( |
| 71 | "{:#x}", | 77 | "{:#x}", |
| 72 | self.send_command_and_get_response(&SetRequest { | 78 | self.send_command_and_get_response(&SetRequest { |
| 73 | pib_attribute_ptr: &short_address as *const _ as *const u8, | 79 | pib_attribute_ptr: &u16::from_be_bytes(short_address) as *const _ as *const u8, |
| 74 | pib_attribute: PibId::ShortAddress, | 80 | pib_attribute: PibId::ShortAddress, |
| 75 | }) | 81 | }) |
| 76 | .await | 82 | .await |
| @@ -78,10 +84,6 @@ impl<'a> Control<'a> { | |||
| 78 | .await | 84 | .await |
| 79 | ); | 85 | ); |
| 80 | 86 | ||
| 81 | critical_section::with(|cs| { | ||
| 82 | self.network_state.borrow(cs).borrow_mut().mac_addr = extended_address.to_be_bytes(); | ||
| 83 | }); | ||
| 84 | |||
| 85 | debug!("setting association permit"); | 87 | debug!("setting association permit"); |
| 86 | let association_permit: bool = true; | 88 | let association_permit: bool = true; |
| 87 | debug!( | 89 | debug!( |
| @@ -186,20 +188,8 @@ impl<'a> Future for EventToken<'a> { | |||
| 186 | type Output = MacEvent<'a>; | 188 | type Output = MacEvent<'a>; |
| 187 | 189 | ||
| 188 | fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | 190 | fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { |
| 189 | self.rx_event_channel.lock(|s| { | 191 | self.rx_event_channel |
| 190 | let signal = s.borrow_mut(); | 192 | .lock(|s| s.borrow_mut().as_mut().unwrap().wait().poll_unpin(cx)) |
| 191 | let signal = match &*signal { | ||
| 192 | Some(s) => s, | ||
| 193 | _ => unreachable!(), | ||
| 194 | }; | ||
| 195 | |||
| 196 | let result = match signal.wait().poll_unpin(cx) { | ||
| 197 | Poll::Ready(mac_event) => Poll::Ready(mac_event), | ||
| 198 | Poll::Pending => Poll::Pending, | ||
| 199 | }; | ||
| 200 | |||
| 201 | result | ||
| 202 | }) | ||
| 203 | } | 193 | } |
| 204 | } | 194 | } |
| 205 | 195 | ||
diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs index 819299b48..c71fabe09 100644 --- a/embassy-stm32-wpan/src/mac/driver.rs +++ b/embassy-stm32-wpan/src/mac/driver.rs | |||
| @@ -11,12 +11,15 @@ use embassy_sync::mutex::Mutex; | |||
| 11 | use embassy_sync::waitqueue::AtomicWaker; | 11 | use embassy_sync::waitqueue::AtomicWaker; |
| 12 | 12 | ||
| 13 | use crate::mac::event::MacEvent; | 13 | use crate::mac::event::MacEvent; |
| 14 | use crate::mac::indications::write_frame_from_data_indication; | ||
| 14 | use crate::mac::runner::{BUF_SIZE, ZeroCopyPubSub}; | 15 | use crate::mac::runner::{BUF_SIZE, ZeroCopyPubSub}; |
| 15 | use crate::mac::{Control, MTU, Runner}; | 16 | use crate::mac::{Control, MTU, Runner}; |
| 16 | use crate::sub::mac::{Mac, MacRx, MacTx}; | 17 | use crate::sub::mac::{Mac, MacRx, MacTx}; |
| 17 | 18 | ||
| 18 | pub struct NetworkState { | 19 | pub struct NetworkState { |
| 19 | pub mac_addr: [u8; 8], | 20 | pub mac_addr: [u8; 8], |
| 21 | pub short_addr: [u8; 2], | ||
| 22 | pub pan_id: [u8; 2], | ||
| 20 | pub link_state: LinkState, | 23 | pub link_state: LinkState, |
| 21 | pub link_waker: AtomicWaker, | 24 | pub link_waker: AtomicWaker, |
| 22 | } | 25 | } |
| @@ -25,6 +28,8 @@ impl NetworkState { | |||
| 25 | pub const fn new() -> Self { | 28 | pub const fn new() -> Self { |
| 26 | Self { | 29 | Self { |
| 27 | mac_addr: [0u8; 8], | 30 | mac_addr: [0u8; 8], |
| 31 | short_addr: [0u8; 2], | ||
| 32 | pan_id: [0u8; 2], | ||
| 28 | link_state: LinkState::Down, | 33 | link_state: LinkState::Down, |
| 29 | link_waker: AtomicWaker::new(), | 34 | link_waker: AtomicWaker::new(), |
| 30 | } | 35 | } |
| @@ -68,7 +73,11 @@ pub struct Driver<'d> { | |||
| 68 | } | 73 | } |
| 69 | 74 | ||
| 70 | impl<'d> Driver<'d> { | 75 | impl<'d> Driver<'d> { |
| 71 | pub fn new(driver_state: &'d mut DriverState<'d>) -> (Self, Runner<'d>, Control<'d>) { | 76 | pub fn new( |
| 77 | driver_state: &'d mut DriverState<'d>, | ||
| 78 | short_address: [u8; 2], | ||
| 79 | mac_address: [u8; 8], | ||
| 80 | ) -> (Self, Runner<'d>, Control<'d>) { | ||
| 72 | ( | 81 | ( |
| 73 | Self { | 82 | Self { |
| 74 | tx_data_channel: &driver_state.tx_data_channel, | 83 | tx_data_channel: &driver_state.tx_data_channel, |
| @@ -85,6 +94,8 @@ impl<'d> Driver<'d> { | |||
| 85 | &driver_state.mac_tx, | 94 | &driver_state.mac_tx, |
| 86 | &mut driver_state.tx_buf_queue, | 95 | &mut driver_state.tx_buf_queue, |
| 87 | &driver_state.network_state, | 96 | &driver_state.network_state, |
| 97 | short_address, | ||
| 98 | mac_address, | ||
| 88 | ), | 99 | ), |
| 89 | Control::new( | 100 | Control::new( |
| 90 | &driver_state.rx_event_channel, | 101 | &driver_state.rx_event_channel, |
| @@ -169,14 +180,13 @@ impl<'d> embassy_net_driver::RxToken for RxToken<'d> { | |||
| 169 | where | 180 | where |
| 170 | F: FnOnce(&mut [u8]) -> R, | 181 | F: FnOnce(&mut [u8]) -> R, |
| 171 | { | 182 | { |
| 172 | // Only valid data events should be put into the queue | 183 | let mut buffer = [0u8; MTU]; |
| 173 | 184 | match self.rx.try_receive().unwrap() { | |
| 174 | let data_event = match self.rx.try_receive().unwrap() { | 185 | MacEvent::McpsDataInd(data_event) => write_frame_from_data_indication(data_event, &mut buffer), |
| 175 | MacEvent::McpsDataInd(data_event) => data_event, | 186 | _ => {} |
| 176 | _ => unreachable!(), | ||
| 177 | }; | 187 | }; |
| 178 | 188 | ||
| 179 | f(&mut data_event.payload()) | 189 | f(&mut buffer[..]) |
| 180 | } | 190 | } |
| 181 | } | 191 | } |
| 182 | 192 | ||
diff --git a/embassy-stm32-wpan/src/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs index c0b86d745..05869ba2a 100644 --- a/embassy-stm32-wpan/src/mac/indications.rs +++ b/embassy-stm32-wpan/src/mac/indications.rs | |||
| @@ -1,5 +1,8 @@ | |||
| 1 | use core::slice; | 1 | use core::slice; |
| 2 | 2 | ||
| 3 | use smoltcp::wire::Ieee802154FrameType; | ||
| 4 | use smoltcp::wire::ieee802154::Frame; | ||
| 5 | |||
| 3 | use super::consts::MAX_PENDING_ADDRESS; | 6 | use super::consts::MAX_PENDING_ADDRESS; |
| 4 | use super::event::ParseableMacEvent; | 7 | use super::event::ParseableMacEvent; |
| 5 | use super::typedefs::{ | 8 | use super::typedefs::{ |
| @@ -250,6 +253,21 @@ impl DataIndication { | |||
| 250 | } | 253 | } |
| 251 | } | 254 | } |
| 252 | 255 | ||
| 256 | pub fn write_frame_from_data_indication<'a, T: AsRef<[u8]> + AsMut<[u8]>>(data: &'a DataIndication, buffer: &'a mut T) { | ||
| 257 | let mut frame = Frame::new_unchecked(buffer); | ||
| 258 | |||
| 259 | // TODO: complete frame creation | ||
| 260 | frame.set_frame_type(Ieee802154FrameType::Data); | ||
| 261 | frame.set_dst_addr(data.dst_address.into()); | ||
| 262 | frame.set_src_addr(data.src_address.into()); | ||
| 263 | frame.set_dst_pan_id(data.dst_pan_id.into()); | ||
| 264 | frame.set_src_pan_id(data.src_pan_id.into()); | ||
| 265 | frame.set_sequence_number(data.dsn); | ||
| 266 | |||
| 267 | // No way around the copy with the current API | ||
| 268 | frame.payload_mut().unwrap().copy_from_slice(data.payload()); | ||
| 269 | } | ||
| 270 | |||
| 253 | /// MLME POLL Indication which will be used for indicating the Data Request | 271 | /// MLME POLL Indication which will be used for indicating the Data Request |
| 254 | /// reception to upper layer as defined in Zigbee r22 - D.8.2 | 272 | /// reception to upper layer as defined in Zigbee r22 - D.8.2 |
| 255 | #[repr(C)] | 273 | #[repr(C)] |
diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index 26fdf23e0..acca70019 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs | |||
| @@ -6,12 +6,13 @@ use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; | |||
| 6 | use embassy_sync::channel::Channel; | 6 | use embassy_sync::channel::Channel; |
| 7 | use embassy_sync::mutex::Mutex; | 7 | use embassy_sync::mutex::Mutex; |
| 8 | use embassy_sync::signal::Signal; | 8 | use embassy_sync::signal::Signal; |
| 9 | use smoltcp::wire::Ieee802154FrameType; | ||
| 10 | use smoltcp::wire::ieee802154::Frame; | ||
| 9 | 11 | ||
| 10 | use crate::mac::MTU; | 12 | use crate::mac::MTU; |
| 11 | use crate::mac::commands::*; | 13 | use crate::mac::commands::*; |
| 12 | use crate::mac::driver::NetworkState; | 14 | use crate::mac::driver::NetworkState; |
| 13 | use crate::mac::event::MacEvent; | 15 | use crate::mac::event::MacEvent; |
| 14 | use crate::mac::typedefs::*; | ||
| 15 | use crate::sub::mac::{MacRx, MacTx}; | 16 | use crate::sub::mac::{MacRx, MacTx}; |
| 16 | 17 | ||
| 17 | pub type ZeroCopyPubSub<M, T> = blocking_mutex::Mutex<M, RefCell<Option<Signal<NoopRawMutex, T>>>>; | 18 | pub type ZeroCopyPubSub<M, T> = blocking_mutex::Mutex<M, RefCell<Option<Signal<NoopRawMutex, T>>>>; |
| @@ -34,7 +35,7 @@ pub struct Runner<'a> { | |||
| 34 | } | 35 | } |
| 35 | 36 | ||
| 36 | impl<'a> Runner<'a> { | 37 | impl<'a> Runner<'a> { |
| 37 | pub fn new( | 38 | pub(crate) fn new( |
| 38 | rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>, | 39 | rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>, |
| 39 | rx_data_channel: &'a Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>, | 40 | rx_data_channel: &'a Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>, |
| 40 | mac_rx: &'a mut MacRx, | 41 | mac_rx: &'a mut MacRx, |
| @@ -43,11 +44,20 @@ impl<'a> Runner<'a> { | |||
| 43 | mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx>, | 44 | mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx>, |
| 44 | tx_buf_queue: &'a mut [[u8; MTU]; BUF_SIZE], | 45 | tx_buf_queue: &'a mut [[u8; MTU]; BUF_SIZE], |
| 45 | network_state: &'a blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>, | 46 | network_state: &'a blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>, |
| 47 | short_address: [u8; 2], | ||
| 48 | mac_address: [u8; 8], | ||
| 46 | ) -> Self { | 49 | ) -> Self { |
| 47 | for buf in tx_buf_queue { | 50 | for buf in tx_buf_queue { |
| 48 | tx_buf_channel.try_send(buf).unwrap(); | 51 | tx_buf_channel.try_send(buf).unwrap(); |
| 49 | } | 52 | } |
| 50 | 53 | ||
| 54 | critical_section::with(|cs| { | ||
| 55 | let mut network_state = network_state.borrow(cs).borrow_mut(); | ||
| 56 | |||
| 57 | network_state.mac_addr = mac_address; | ||
| 58 | network_state.short_addr = short_address; | ||
| 59 | }); | ||
| 60 | |||
| 51 | Self { | 61 | Self { |
| 52 | rx_event_channel, | 62 | rx_event_channel, |
| 53 | rx_data_channel, | 63 | rx_data_channel, |
| @@ -59,58 +69,75 @@ impl<'a> Runner<'a> { | |||
| 59 | } | 69 | } |
| 60 | } | 70 | } |
| 61 | 71 | ||
| 72 | async fn send_request<T: MacCommand, U: TryInto<T>>(&self, frame: U) -> Result<(), ()> | ||
| 73 | where | ||
| 74 | (): From<<U as TryInto<T>>::Error>, | ||
| 75 | { | ||
| 76 | let request: T = frame.try_into()?; | ||
| 77 | self.mac_tx.lock().await.send_command(&request).await.map_err(|_| ())?; | ||
| 78 | |||
| 79 | Ok(()) | ||
| 80 | } | ||
| 81 | |||
| 62 | pub async fn run(&'a self) -> ! { | 82 | pub async fn run(&'a self) -> ! { |
| 63 | join::join( | 83 | join::join( |
| 64 | async { | 84 | async { |
| 65 | loop { | 85 | loop { |
| 66 | if let Ok(mac_event) = self.mac_rx.read().await { | 86 | if let Ok(mac_event) = self.mac_rx.read().await { |
| 67 | match mac_event { | 87 | match mac_event { |
| 88 | MacEvent::MlmeAssociateCnf(_) | ||
| 89 | | MacEvent::MlmeDisassociateCnf(_) | ||
| 90 | | MacEvent::MlmeGetCnf(_) | ||
| 91 | | MacEvent::MlmeGtsCnf(_) | ||
| 92 | | MacEvent::MlmeResetCnf(_) | ||
| 93 | | MacEvent::MlmeRxEnableCnf(_) | ||
| 94 | | MacEvent::MlmeScanCnf(_) | ||
| 95 | | MacEvent::MlmeSetCnf(_) | ||
| 96 | | MacEvent::MlmeStartCnf(_) | ||
| 97 | | MacEvent::MlmePollCnf(_) | ||
| 98 | | MacEvent::MlmeDpsCnf(_) | ||
| 99 | | MacEvent::MlmeSoundingCnf(_) | ||
| 100 | | MacEvent::MlmeCalibrateCnf(_) | ||
| 101 | | MacEvent::McpsDataCnf(_) | ||
| 102 | | MacEvent::McpsPurgeCnf(_) => { | ||
| 103 | self.rx_event_channel.lock(|s| { | ||
| 104 | s.borrow().as_ref().map(|signal| signal.signal(mac_event)); | ||
| 105 | }); | ||
| 106 | } | ||
| 68 | MacEvent::McpsDataInd(_) => { | 107 | MacEvent::McpsDataInd(_) => { |
| 108 | // Pattern should match driver | ||
| 69 | self.rx_data_channel.send(mac_event).await; | 109 | self.rx_data_channel.send(mac_event).await; |
| 70 | } | 110 | } |
| 71 | _ => { | 111 | _ => { |
| 72 | self.rx_event_channel.lock(|s| { | 112 | debug!("unhandled mac event: {:#x}", mac_event); |
| 73 | match &*s.borrow() { | ||
| 74 | Some(signal) => { | ||
| 75 | signal.signal(mac_event); | ||
| 76 | } | ||
| 77 | None => {} | ||
| 78 | }; | ||
| 79 | }); | ||
| 80 | } | 113 | } |
| 81 | } | 114 | } |
| 82 | } | 115 | } |
| 83 | } | 116 | } |
| 84 | }, | 117 | }, |
| 85 | async { | 118 | async { |
| 86 | let mut msdu_handle = 0x02; | ||
| 87 | |||
| 88 | loop { | 119 | loop { |
| 89 | let (buf, len) = self.tx_data_channel.receive().await; | 120 | let (buf, _) = self.tx_data_channel.receive().await; |
| 90 | let mac_tx = self.mac_tx.lock().await; | 121 | |
| 91 | 122 | // Smoltcp has created this frame, so there's no need to reparse it. | |
| 92 | // TODO: skip this if the link state is down | 123 | let frame = Frame::new_unchecked(&buf); |
| 93 | 124 | ||
| 94 | // The mutex should be dropped on the next loop iteration | 125 | let result: Result<(), ()> = match frame.frame_type() { |
| 95 | mac_tx | 126 | Ieee802154FrameType::Beacon => Err(()), |
| 96 | .send_command( | 127 | Ieee802154FrameType::Data => self.send_request::<DataRequest, _>(frame).await, |
| 97 | DataRequest { | 128 | Ieee802154FrameType::Acknowledgement => Err(()), |
| 98 | src_addr_mode: AddressMode::Short, | 129 | Ieee802154FrameType::MacCommand => Err(()), |
| 99 | dst_addr_mode: AddressMode::Short, | 130 | Ieee802154FrameType::Multipurpose => Err(()), |
| 100 | dst_pan_id: PanId([0x1A, 0xAA]), | 131 | Ieee802154FrameType::FragmentOrFrak => Err(()), |
| 101 | dst_address: MacAddress::BROADCAST, | 132 | Ieee802154FrameType::Extended => Err(()), |
| 102 | msdu_handle: msdu_handle, | 133 | _ => Err(()), |
| 103 | ack_tx: 0x00, | 134 | }; |
| 104 | gts_tx: false, | 135 | |
| 105 | security_level: SecurityLevel::Unsecure, | 136 | if result.is_err() { |
| 106 | ..Default::default() | 137 | debug!("failed to parse mac frame"); |
| 107 | } | 138 | } else { |
| 108 | .set_buffer(&buf[..len]), | 139 | trace!("data frame sent!"); |
| 109 | ) | 140 | } |
| 110 | .await | ||
| 111 | .unwrap(); | ||
| 112 | |||
| 113 | msdu_handle = msdu_handle.wrapping_add(1); | ||
| 114 | 141 | ||
| 115 | // The tx channel should always be of equal capacity to the tx_buf channel | 142 | // The tx channel should always be of equal capacity to the tx_buf channel |
| 116 | self.tx_buf_channel.try_send(buf).unwrap(); | 143 | self.tx_buf_channel.try_send(buf).unwrap(); |
diff --git a/embassy-stm32-wpan/src/mac/typedefs.rs b/embassy-stm32-wpan/src/mac/typedefs.rs index 0552b8ea1..7e3ef4962 100644 --- a/embassy-stm32-wpan/src/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/mac/typedefs.rs | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | use core::fmt::Debug; | 1 | use core::fmt::Debug; |
| 2 | 2 | ||
| 3 | use smoltcp::wire::ieee802154::{Address, AddressingMode, Pan}; | ||
| 4 | |||
| 3 | use crate::numeric_enum; | 5 | use crate::numeric_enum; |
| 4 | 6 | ||
| 5 | #[derive(Debug)] | 7 | #[derive(Debug)] |
| @@ -109,12 +111,41 @@ numeric_enum! { | |||
| 109 | } | 111 | } |
| 110 | } | 112 | } |
| 111 | 113 | ||
| 114 | impl TryFrom<AddressingMode> for AddressMode { | ||
| 115 | type Error = (); | ||
| 116 | |||
| 117 | fn try_from(value: AddressingMode) -> Result<Self, Self::Error> { | ||
| 118 | match value { | ||
| 119 | AddressingMode::Absent => Ok(Self::NoAddress), | ||
| 120 | AddressingMode::Extended => Ok(Self::Extended), | ||
| 121 | AddressingMode::Short => Ok(Self::Short), | ||
| 122 | AddressingMode::Unknown(_) => Err(()), | ||
| 123 | } | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 112 | #[derive(Clone, Copy)] | 127 | #[derive(Clone, Copy)] |
| 113 | pub union MacAddress { | 128 | pub union MacAddress { |
| 114 | pub short: [u8; 2], | 129 | pub short: [u8; 2], |
| 115 | pub extended: [u8; 8], | 130 | pub extended: [u8; 8], |
| 116 | } | 131 | } |
| 117 | 132 | ||
| 133 | impl From<Address> for MacAddress { | ||
| 134 | fn from(value: Address) -> Self { | ||
| 135 | match value { | ||
| 136 | Address::Short(addr) => Self { short: addr }, | ||
| 137 | Address::Extended(addr) => Self { extended: addr }, | ||
| 138 | Address::Absent => Self { short: [0u8; 2] }, | ||
| 139 | } | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | impl From<MacAddress> for Address { | ||
| 144 | fn from(_value: MacAddress) -> Self { | ||
| 145 | todo!() | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 118 | impl Debug for MacAddress { | 149 | impl Debug for MacAddress { |
| 119 | fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | 150 | fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
| 120 | unsafe { | 151 | unsafe { |
| @@ -379,3 +410,15 @@ pub struct PanId(pub [u8; 2]); | |||
| 379 | impl PanId { | 410 | impl PanId { |
| 380 | pub const BROADCAST: Self = Self([0xFF, 0xFF]); | 411 | pub const BROADCAST: Self = Self([0xFF, 0xFF]); |
| 381 | } | 412 | } |
| 413 | |||
| 414 | impl From<Pan> for PanId { | ||
| 415 | fn from(value: Pan) -> Self { | ||
| 416 | Self(value.0.to_be_bytes()) | ||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 420 | impl From<PanId> for Pan { | ||
| 421 | fn from(value: PanId) -> Self { | ||
| 422 | Self(u16::from_be_bytes(value.0)) | ||
| 423 | } | ||
| 424 | } | ||
diff --git a/embassy-stm32-wpan/src/sub/mm.rs b/embassy-stm32-wpan/src/sub/mm.rs index 62d0de8bd..a90c6ee55 100644 --- a/embassy-stm32-wpan/src/sub/mm.rs +++ b/embassy-stm32-wpan/src/sub/mm.rs | |||
| @@ -46,7 +46,7 @@ impl MemoryManager { | |||
| 46 | Self { _private: () } | 46 | Self { _private: () } |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | pub async fn run_queue(&self) { | 49 | pub async fn run_queue(&self) -> ! { |
| 50 | loop { | 50 | loop { |
| 51 | poll_fn(|cx| unsafe { | 51 | poll_fn(|cx| unsafe { |
| 52 | MM_WAKER.register(cx.waker()); | 52 | MM_WAKER.register(cx.waker()); |
diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs index 9b705dda9..5d946b35b 100644 --- a/examples/stm32wb/src/bin/mac_ffd_net.rs +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs | |||
| @@ -1,30 +1,44 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::net::Ipv6Addr; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_net::udp::{PacketMetadata, UdpSocket}; | ||
| 9 | use embassy_net::{Ipv6Cidr, StackResources, StaticConfigV6}; | ||
| 6 | use embassy_stm32::bind_interrupts; | 10 | use embassy_stm32::bind_interrupts; |
| 7 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | 11 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; |
| 12 | use embassy_stm32::peripherals::RNG; | ||
| 8 | use embassy_stm32::rcc::WPAN_DEFAULT; | 13 | use embassy_stm32::rcc::WPAN_DEFAULT; |
| 14 | use embassy_stm32::rng::InterruptHandler as RngInterruptHandler; | ||
| 9 | use embassy_stm32_wpan::TlMbox; | 15 | use embassy_stm32_wpan::TlMbox; |
| 10 | use embassy_stm32_wpan::mac::{Driver, DriverState, Runner}; | 16 | use embassy_stm32_wpan::mac::{Driver, DriverState, Runner}; |
| 11 | use embassy_stm32_wpan::sub::mm; | 17 | use embassy_stm32_wpan::sub::mm; |
| 18 | use embassy_time::{Duration, Timer}; | ||
| 19 | use heapless::Vec; | ||
| 12 | use static_cell::StaticCell; | 20 | use static_cell::StaticCell; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 21 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 22 | ||
| 15 | bind_interrupts!(struct Irqs{ | 23 | bind_interrupts!(struct Irqs{ |
| 16 | IPCC_C1_RX => ReceiveInterruptHandler; | 24 | IPCC_C1_RX => ReceiveInterruptHandler; |
| 17 | IPCC_C1_TX => TransmitInterruptHandler; | 25 | IPCC_C1_TX => TransmitInterruptHandler; |
| 26 | RNG => RngInterruptHandler<RNG>; | ||
| 18 | }); | 27 | }); |
| 19 | 28 | ||
| 20 | #[embassy_executor::task] | 29 | #[embassy_executor::task] |
| 21 | async fn run_mm_queue(memory_manager: mm::MemoryManager) { | 30 | async fn run_mm_queue(memory_manager: mm::MemoryManager) -> ! { |
| 22 | memory_manager.run_queue().await; | 31 | memory_manager.run_queue().await |
| 32 | } | ||
| 33 | |||
| 34 | #[embassy_executor::task] | ||
| 35 | async fn run_mac(runner: &'static Runner<'static>) -> ! { | ||
| 36 | runner.run().await | ||
| 23 | } | 37 | } |
| 24 | 38 | ||
| 25 | #[embassy_executor::task] | 39 | #[embassy_executor::task] |
| 26 | async fn run_mac(runner: &'static Runner<'static>) { | 40 | async fn run_net(mut runner: embassy_net::Runner<'static, Driver<'static>>) -> ! { |
| 27 | runner.run().await; | 41 | runner.run().await |
| 28 | } | 42 | } |
| 29 | 43 | ||
| 30 | #[embassy_executor::main] | 44 | #[embassy_executor::main] |
| @@ -72,21 +86,67 @@ async fn main(spawner: Spawner) { | |||
| 72 | 86 | ||
| 73 | static DRIVER_STATE: StaticCell<DriverState> = StaticCell::new(); | 87 | static DRIVER_STATE: StaticCell<DriverState> = StaticCell::new(); |
| 74 | static RUNNER: StaticCell<Runner> = StaticCell::new(); | 88 | static RUNNER: StaticCell<Runner> = StaticCell::new(); |
| 89 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | ||
| 75 | 90 | ||
| 76 | let driver_state = DRIVER_STATE.init(DriverState::new(mbox.mac_subsystem)); | 91 | let driver_state = DRIVER_STATE.init(DriverState::new(mbox.mac_subsystem)); |
| 77 | let (driver, runner, mut control) = Driver::new(driver_state); | ||
| 78 | 92 | ||
| 79 | spawner.spawn(run_mac(RUNNER.init(runner)).unwrap()); | 93 | let (driver, mac_runner, mut control) = Driver::new( |
| 94 | driver_state, | ||
| 95 | 0x1122u16.to_be_bytes().try_into().unwrap(), | ||
| 96 | 0xACDE480000000001u64.to_be_bytes().try_into().unwrap(), | ||
| 97 | ); | ||
| 80 | 98 | ||
| 81 | control | 99 | // TODO: rng does not work for some reason |
| 82 | .init_link( | 100 | // Generate random seed. |
| 83 | 0x1122u16.to_be_bytes().try_into().unwrap(), | 101 | // let mut rng = Rng::new(p.RNG, Irqs); |
| 84 | 0xACDE480000000001u64.to_be_bytes().try_into().unwrap(), | 102 | let seed = [0; 8]; |
| 85 | [0x1A, 0xAA], | 103 | // let _ = rng.async_fill_bytes(&mut seed).await; |
| 86 | ) | 104 | let seed = u64::from_le_bytes(seed); |
| 87 | .await; | ||
| 88 | 105 | ||
| 89 | cortex_m::asm::bkpt(); | 106 | info!("seed generated"); |
| 107 | |||
| 108 | // Init network stack | ||
| 109 | let ipv6_addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); | ||
| 110 | |||
| 111 | let config = embassy_net::Config::ipv6_static(StaticConfigV6 { | ||
| 112 | address: Ipv6Cidr::new(ipv6_addr, 104), | ||
| 113 | gateway: None, | ||
| 114 | dns_servers: Vec::new(), | ||
| 115 | }); | ||
| 116 | |||
| 117 | let (stack, eth_runner) = embassy_net::new(driver, config, RESOURCES.init(StackResources::new()), seed); | ||
| 118 | |||
| 119 | // wpan runner | ||
| 120 | spawner.spawn(run_mac(RUNNER.init(mac_runner)).unwrap()); | ||
| 121 | |||
| 122 | // Launch network task | ||
| 123 | spawner.spawn(unwrap!(run_net(eth_runner))); | ||
| 124 | |||
| 125 | info!("Network task initialized"); | ||
| 90 | 126 | ||
| 91 | let _ = driver; | 127 | control.init_link([0x1A, 0xAA]).await; |
| 128 | |||
| 129 | // Ensure DHCP configuration is up before trying connect | ||
| 130 | stack.wait_config_up().await; | ||
| 131 | |||
| 132 | info!("Network up"); | ||
| 133 | |||
| 134 | // Then we can use it! | ||
| 135 | let mut rx_meta = [PacketMetadata::EMPTY]; | ||
| 136 | let mut rx_buffer = [0; 4096]; | ||
| 137 | let mut tx_meta = [PacketMetadata::EMPTY]; | ||
| 138 | let mut tx_buffer = [0; 4096]; | ||
| 139 | |||
| 140 | let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); | ||
| 141 | |||
| 142 | let remote_endpoint = (Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2fb), 8000); | ||
| 143 | |||
| 144 | let send_buf = [0u8; 20]; | ||
| 145 | |||
| 146 | socket.bind((ipv6_addr, 8000)).unwrap(); | ||
| 147 | socket.send_to(&send_buf, remote_endpoint).await.unwrap(); | ||
| 148 | |||
| 149 | Timer::after(Duration::from_secs(2)).await; | ||
| 150 | |||
| 151 | cortex_m::asm::bkpt(); | ||
| 92 | } | 152 | } |
