aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-17 17:27:25 +0000
committerGitHub <[email protected]>2025-11-17 17:27:25 +0000
commit45797ecb8501d7a22c53967fad45ee7490424991 (patch)
tree6b61248333bbc9f12948ca9689104bc03d592757
parent9cd6c92151e4ee68bca95bfc17658e50ad2c1aca (diff)
parentca02cdf792d4aff16e2f265616bec5abdb3c7a1a (diff)
Merge pull request #4905 from xoviat/wpan
wpan: get embasy_net actually working parse frames correctly
-rw-r--r--embassy-stm32-wpan/Cargo.toml3
-rw-r--r--embassy-stm32-wpan/src/mac/commands.rs26
-rw-r--r--embassy-stm32-wpan/src/mac/control.rs36
-rw-r--r--embassy-stm32-wpan/src/mac/driver.rs24
-rw-r--r--embassy-stm32-wpan/src/mac/indications.rs18
-rw-r--r--embassy-stm32-wpan/src/mac/runner.rs101
-rw-r--r--embassy-stm32-wpan/src/mac/typedefs.rs43
-rw-r--r--embassy-stm32-wpan/src/sub/mm.rs2
-rw-r--r--examples/stm32wb/src/bin/mac_ffd_net.rs90
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" }
33embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" } 33embassy-hal-internal = { version = "0.3.0", path = "../embassy-hal-internal" }
34embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal" } 34embassy-embedded-hal = { version = "0.5.0", path = "../embassy-embedded-hal" }
35embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", optional=true } 35embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver", optional=true }
36smoltcp = { version = "0.12.0", optional=true, default-features = false }
36 37
37defmt = { version = "1.0.1", optional = true } 38defmt = { version = "1.0.1", optional = true }
38log = { version = "0.4.17", optional = true } 39log = { version = "0.4.17", optional = true }
@@ -52,7 +53,7 @@ bitflags = { version = "2.3.3", optional = true }
52defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "stm32wb-hci?/defmt"] 53defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "stm32wb-hci?/defmt"]
53 54
54ble = ["dep:stm32wb-hci"] 55ble = ["dep:stm32wb-hci"]
55mac = ["dep:bitflags", "dep:embassy-net-driver" ] 56mac = ["dep:bitflags", "dep:embassy-net-driver", "dep:smoltcp", "smoltcp/medium-ieee802154"]
56 57
57extended = [] 58extended = []
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
3use core::{mem, slice}; 3use core::{mem, slice};
4 4
5use smoltcp::wire::ieee802154::Frame;
6
5use super::opcodes::OpcodeM4ToM0; 7use super::opcodes::OpcodeM4ToM0;
6use super::typedefs::{ 8use 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
384impl<'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
382impl Default for DataRequest { 408impl 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;
11use embassy_sync::waitqueue::AtomicWaker; 11use embassy_sync::waitqueue::AtomicWaker;
12 12
13use crate::mac::event::MacEvent; 13use crate::mac::event::MacEvent;
14use crate::mac::indications::write_frame_from_data_indication;
14use crate::mac::runner::{BUF_SIZE, ZeroCopyPubSub}; 15use crate::mac::runner::{BUF_SIZE, ZeroCopyPubSub};
15use crate::mac::{Control, MTU, Runner}; 16use crate::mac::{Control, MTU, Runner};
16use crate::sub::mac::{Mac, MacRx, MacTx}; 17use crate::sub::mac::{Mac, MacRx, MacTx};
17 18
18pub struct NetworkState { 19pub 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
70impl<'d> Driver<'d> { 75impl<'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 @@
1use core::slice; 1use core::slice;
2 2
3use smoltcp::wire::Ieee802154FrameType;
4use smoltcp::wire::ieee802154::Frame;
5
3use super::consts::MAX_PENDING_ADDRESS; 6use super::consts::MAX_PENDING_ADDRESS;
4use super::event::ParseableMacEvent; 7use super::event::ParseableMacEvent;
5use super::typedefs::{ 8use super::typedefs::{
@@ -250,6 +253,21 @@ impl DataIndication {
250 } 253 }
251} 254}
252 255
256pub 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};
6use embassy_sync::channel::Channel; 6use embassy_sync::channel::Channel;
7use embassy_sync::mutex::Mutex; 7use embassy_sync::mutex::Mutex;
8use embassy_sync::signal::Signal; 8use embassy_sync::signal::Signal;
9use smoltcp::wire::Ieee802154FrameType;
10use smoltcp::wire::ieee802154::Frame;
9 11
10use crate::mac::MTU; 12use crate::mac::MTU;
11use crate::mac::commands::*; 13use crate::mac::commands::*;
12use crate::mac::driver::NetworkState; 14use crate::mac::driver::NetworkState;
13use crate::mac::event::MacEvent; 15use crate::mac::event::MacEvent;
14use crate::mac::typedefs::*;
15use crate::sub::mac::{MacRx, MacTx}; 16use crate::sub::mac::{MacRx, MacTx};
16 17
17pub type ZeroCopyPubSub<M, T> = blocking_mutex::Mutex<M, RefCell<Option<Signal<NoopRawMutex, T>>>>; 18pub 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
36impl<'a> Runner<'a> { 37impl<'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 @@
1use core::fmt::Debug; 1use core::fmt::Debug;
2 2
3use smoltcp::wire::ieee802154::{Address, AddressingMode, Pan};
4
3use crate::numeric_enum; 5use crate::numeric_enum;
4 6
5#[derive(Debug)] 7#[derive(Debug)]
@@ -109,12 +111,41 @@ numeric_enum! {
109} 111}
110} 112}
111 113
114impl 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)]
113pub union MacAddress { 128pub 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
133impl 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
143impl From<MacAddress> for Address {
144 fn from(_value: MacAddress) -> Self {
145 todo!()
146 }
147}
148
118impl Debug for MacAddress { 149impl 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]);
379impl PanId { 410impl PanId {
380 pub const BROADCAST: Self = Self([0xFF, 0xFF]); 411 pub const BROADCAST: Self = Self([0xFF, 0xFF]);
381} 412}
413
414impl From<Pan> for PanId {
415 fn from(value: Pan) -> Self {
416 Self(value.0.to_be_bytes())
417 }
418}
419
420impl 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
4use core::net::Ipv6Addr;
5
4use defmt::*; 6use defmt::*;
5use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_net::udp::{PacketMetadata, UdpSocket};
9use embassy_net::{Ipv6Cidr, StackResources, StaticConfigV6};
6use embassy_stm32::bind_interrupts; 10use embassy_stm32::bind_interrupts;
7use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 11use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
12use embassy_stm32::peripherals::RNG;
8use embassy_stm32::rcc::WPAN_DEFAULT; 13use embassy_stm32::rcc::WPAN_DEFAULT;
14use embassy_stm32::rng::InterruptHandler as RngInterruptHandler;
9use embassy_stm32_wpan::TlMbox; 15use embassy_stm32_wpan::TlMbox;
10use embassy_stm32_wpan::mac::{Driver, DriverState, Runner}; 16use embassy_stm32_wpan::mac::{Driver, DriverState, Runner};
11use embassy_stm32_wpan::sub::mm; 17use embassy_stm32_wpan::sub::mm;
18use embassy_time::{Duration, Timer};
19use heapless::Vec;
12use static_cell::StaticCell; 20use static_cell::StaticCell;
13use {defmt_rtt as _, panic_probe as _}; 21use {defmt_rtt as _, panic_probe as _};
14 22
15bind_interrupts!(struct Irqs{ 23bind_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]
21async fn run_mm_queue(memory_manager: mm::MemoryManager) { 30async 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]
35async fn run_mac(runner: &'static Runner<'static>) -> ! {
36 runner.run().await
23} 37}
24 38
25#[embassy_executor::task] 39#[embassy_executor::task]
26async fn run_mac(runner: &'static Runner<'static>) { 40async 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}