aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-07-21 22:29:15 +0000
committerGitHub <[email protected]>2023-07-21 22:29:15 +0000
commit4db63677f6e56c52ea3d432542513967f5d93c69 (patch)
treead109082d957fced3b0e9a33ba74f3a47ea1da54
parent4d1d125f4157084668a949f9bc24e4417628f9fe (diff)
parentf4d6a23f92c8f6d3eb97a09e5bc51bac5e8d6837 (diff)
Merge pull request #1658 from xoviat/mac
implement most infra for wpan mac
-rw-r--r--embassy-net-driver/src/lib.rs3
-rw-r--r--embassy-net/Cargo.toml1
-rw-r--r--embassy-net/src/device.rs2
-rw-r--r--embassy-net/src/lib.rs13
-rw-r--r--embassy-stm32-wpan/Cargo.toml4
-rw-r--r--embassy-stm32-wpan/src/lib.rs3
-rw-r--r--embassy-stm32-wpan/src/mac/control.rs95
-rw-r--r--embassy-stm32-wpan/src/mac/driver.rs122
-rw-r--r--embassy-stm32-wpan/src/mac/event.rs159
-rw-r--r--embassy-stm32-wpan/src/mac/indications.rs14
-rw-r--r--embassy-stm32-wpan/src/mac/mod.rs13
-rw-r--r--embassy-stm32-wpan/src/mac/responses.rs21
-rw-r--r--embassy-stm32-wpan/src/mac/runner.rs109
-rw-r--r--embassy-stm32-wpan/src/mac/typedefs.rs32
-rw-r--r--embassy-stm32-wpan/src/sub/mac.rs10
-rw-r--r--embassy-sync/src/channel.rs22
-rw-r--r--examples/stm32wb/Cargo.toml9
-rw-r--r--examples/stm32wb/src/bin/mac_ffd.rs37
-rw-r--r--examples/stm32wb/src/bin/mac_ffd_net.rs170
-rw-r--r--examples/stm32wb/src/bin/mac_rfd.rs36
-rw-r--r--tests/stm32/src/bin/wpan_mac.rs26
21 files changed, 764 insertions, 137 deletions
diff --git a/embassy-net-driver/src/lib.rs b/embassy-net-driver/src/lib.rs
index 4149bf4a4..09def20c4 100644
--- a/embassy-net-driver/src/lib.rs
+++ b/embassy-net-driver/src/lib.rs
@@ -164,6 +164,9 @@ pub enum Medium {
164 /// 164 ///
165 /// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode. 165 /// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode.
166 Ip, 166 Ip,
167
168 /// IEEE 802_15_4 medium
169 Ieee802154,
167} 170}
168 171
169impl Default for Medium { 172impl Default for Medium {
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml
index 6dc429ddc..9b6a11c16 100644
--- a/embassy-net/Cargo.toml
+++ b/embassy-net/Cargo.toml
@@ -37,6 +37,7 @@ proto-ipv4 = ["smoltcp/proto-ipv4"]
37proto-ipv6 = ["smoltcp/proto-ipv6"] 37proto-ipv6 = ["smoltcp/proto-ipv6"]
38medium-ethernet = ["smoltcp/medium-ethernet"] 38medium-ethernet = ["smoltcp/medium-ethernet"]
39medium-ip = ["smoltcp/medium-ip"] 39medium-ip = ["smoltcp/medium-ip"]
40medium-ieee802154 = ["smoltcp/medium-ieee802154"]
40igmp = ["smoltcp/proto-igmp"] 41igmp = ["smoltcp/proto-igmp"]
41 42
42[dependencies] 43[dependencies]
diff --git a/embassy-net/src/device.rs b/embassy-net/src/device.rs
index 4513c86d3..d29ab8970 100644
--- a/embassy-net/src/device.rs
+++ b/embassy-net/src/device.rs
@@ -51,6 +51,8 @@ where
51 Medium::Ethernet => phy::Medium::Ethernet, 51 Medium::Ethernet => phy::Medium::Ethernet,
52 #[cfg(feature = "medium-ip")] 52 #[cfg(feature = "medium-ip")]
53 Medium::Ip => phy::Medium::Ip, 53 Medium::Ip => phy::Medium::Ip,
54 #[cfg(feature = "medium-ieee802154")]
55 Medium::Ieee802154 => phy::Medium::Ieee802154,
54 #[allow(unreachable_patterns)] 56 #[allow(unreachable_patterns)]
55 _ => panic!( 57 _ => panic!(
56 "Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.", 58 "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 4fbafe752..81c751a2c 100644
--- a/embassy-net/src/lib.rs
+++ b/embassy-net/src/lib.rs
@@ -24,9 +24,11 @@ use embassy_net_driver::{Driver, LinkState, Medium};
24use embassy_sync::waitqueue::WakerRegistration; 24use embassy_sync::waitqueue::WakerRegistration;
25use embassy_time::{Instant, Timer}; 25use embassy_time::{Instant, Timer};
26use futures::pin_mut; 26use futures::pin_mut;
27#[allow(unused_imports)]
27use heapless::Vec; 28use heapless::Vec;
28#[cfg(feature = "igmp")] 29#[cfg(feature = "igmp")]
29pub use smoltcp::iface::MulticastError; 30pub use smoltcp::iface::MulticastError;
31#[allow(unused_imports)]
30use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage}; 32use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage};
31#[cfg(feature = "dhcpv4")] 33#[cfg(feature = "dhcpv4")]
32use smoltcp::socket::dhcpv4::{self, RetryConfig}; 34use smoltcp::socket::dhcpv4::{self, RetryConfig};
@@ -34,6 +36,8 @@ use smoltcp::socket::dhcpv4::{self, RetryConfig};
34pub use smoltcp::wire::IpListenEndpoint; 36pub use smoltcp::wire::IpListenEndpoint;
35#[cfg(feature = "medium-ethernet")] 37#[cfg(feature = "medium-ethernet")]
36pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; 38pub use smoltcp::wire::{EthernetAddress, HardwareAddress};
39#[cfg(feature = "medium-ieee802154")]
40pub use smoltcp::wire::{HardwareAddress, Ieee802154Address};
37pub use smoltcp::wire::{IpAddress, IpCidr, IpEndpoint}; 41pub use smoltcp::wire::{IpAddress, IpCidr, IpEndpoint};
38#[cfg(feature = "proto-ipv4")] 42#[cfg(feature = "proto-ipv4")]
39pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr}; 43pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr};
@@ -232,7 +236,7 @@ impl<D: Driver + 'static> Stack<D> {
232 resources: &'static mut StackResources<SOCK>, 236 resources: &'static mut StackResources<SOCK>,
233 random_seed: u64, 237 random_seed: u64,
234 ) -> Self { 238 ) -> Self {
235 #[cfg(feature = "medium-ethernet")] 239 #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
236 let medium = device.capabilities().medium; 240 let medium = device.capabilities().medium;
237 241
238 let hardware_addr = match medium { 242 let hardware_addr = match medium {
@@ -240,6 +244,8 @@ impl<D: Driver + 'static> Stack<D> {
240 Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress(device.ethernet_address())), 244 Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress(device.ethernet_address())),
241 #[cfg(feature = "medium-ip")] 245 #[cfg(feature = "medium-ip")]
242 Medium::Ip => HardwareAddress::Ip, 246 Medium::Ip => HardwareAddress::Ip,
247 #[cfg(feature = "medium-ieee802154")]
248 Medium::Ieee802154 => HardwareAddress::Ieee802154(Ieee802154Address::Absent),
243 #[allow(unreachable_patterns)] 249 #[allow(unreachable_patterns)]
244 _ => panic!( 250 _ => panic!(
245 "Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.", 251 "Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.",
@@ -262,6 +268,7 @@ impl<D: Driver + 'static> Stack<D> {
262 268
263 let next_local_port = (random_seed % (LOCAL_PORT_MAX - LOCAL_PORT_MIN) as u64) as u16 + LOCAL_PORT_MIN; 269 let next_local_port = (random_seed % (LOCAL_PORT_MAX - LOCAL_PORT_MIN) as u64) as u16 + LOCAL_PORT_MIN;
264 270
271 #[cfg_attr(feature = "medium-ieee802154", allow(unused_mut))]
265 let mut socket = SocketStack { 272 let mut socket = SocketStack {
266 sockets, 273 sockets,
267 iface, 274 iface,
@@ -269,6 +276,7 @@ impl<D: Driver + 'static> Stack<D> {
269 next_local_port, 276 next_local_port,
270 }; 277 };
271 278
279 #[cfg_attr(feature = "medium-ieee802154", allow(unused_mut))]
272 let mut inner = Inner { 280 let mut inner = Inner {
273 device, 281 device,
274 link_up: false, 282 link_up: false,
@@ -287,6 +295,9 @@ impl<D: Driver + 'static> Stack<D> {
287 dns_waker: WakerRegistration::new(), 295 dns_waker: WakerRegistration::new(),
288 }; 296 };
289 297
298 #[cfg(feature = "medium-ieee802154")]
299 let _ = config;
300
290 #[cfg(feature = "proto-ipv4")] 301 #[cfg(feature = "proto-ipv4")]
291 match config.ipv4 { 302 match config.ipv4 {
292 ConfigV4::Static(config) => { 303 ConfigV4::Static(config) => {
diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml
index 868bffe74..6cd122200 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 }
17embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 17embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
18embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } 18embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" }
19embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } 19embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" }
20embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver", optional=true }
20 21
21defmt = { version = "0.3", optional = true } 22defmt = { version = "0.3", optional = true }
22cortex-m = "0.7.6" 23cortex-m = "0.7.6"
@@ -26,13 +27,14 @@ aligned = "0.4.1"
26bit_field = "0.10.2" 27bit_field = "0.10.2"
27stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } 28stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] }
28stm32wb-hci = { version = "0.1.3", optional = true } 29stm32wb-hci = { version = "0.1.3", optional = true }
30futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
29bitflags = { version = "2.3.3", optional = true } 31bitflags = { version = "2.3.3", optional = true }
30 32
31[features] 33[features]
32defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"] 34defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"]
33 35
34ble = ["dep:stm32wb-hci"] 36ble = ["dep:stm32wb-hci"]
35mac = ["dep:bitflags"] 37mac = ["dep:bitflags", "dep:embassy-net-driver" ]
36 38
37stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] 39stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ]
38stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] 40stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ]
diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs
index 57f0dc4fa..6836d7a8b 100644
--- a/embassy-stm32-wpan/src/lib.rs
+++ b/embassy-stm32-wpan/src/lib.rs
@@ -1,5 +1,6 @@
1#![no_std] 1#![no_std]
2#![cfg_attr(feature = "ble", feature(async_fn_in_trait))] 2#![cfg_attr(any(feature = "ble", feature = "mac"), feature(async_fn_in_trait))]
3#![cfg_attr(feature = "mac", feature(type_alias_impl_trait, concat_bytes))]
3 4
4// This must go FIRST so that all the other modules see its macros. 5// This must go FIRST so that all the other modules see its macros.
5pub mod fmt; 6pub 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 000000000..8a13de81c
--- /dev/null
+++ b/embassy-stm32-wpan/src/mac/control.rs
@@ -0,0 +1,95 @@
1use core::future::Future;
2use core::task;
3use core::task::Poll;
4
5use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
6use embassy_sync::mutex::MutexGuard;
7use embassy_sync::signal::Signal;
8use futures::FutureExt;
9
10use super::commands::MacCommand;
11use super::event::MacEvent;
12use super::typedefs::MacError;
13use crate::mac::runner::Runner;
14
15pub struct Control<'a> {
16 runner: &'a Runner<'a>,
17}
18
19impl<'a> Control<'a> {
20 pub(crate) fn new(runner: &'a Runner<'a>) -> Self {
21 Self { runner: runner }
22 }
23
24 pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError>
25 where
26 T: MacCommand,
27 {
28 let _wm = self.runner.write_mutex.lock().await;
29
30 self.runner.mac_subsystem.send_command(cmd).await
31 }
32
33 pub async fn send_command_and_get_response<T>(&self, cmd: &T) -> Result<EventToken<'a>, MacError>
34 where
35 T: MacCommand,
36 {
37 let rm = self.runner.read_mutex.lock().await;
38 let _wm = self.runner.write_mutex.lock().await;
39 let token = EventToken::new(self.runner, rm);
40
41 self.runner.mac_subsystem.send_command(cmd).await?;
42
43 Ok(token)
44 }
45}
46
47pub struct EventToken<'a> {
48 runner: &'a Runner<'a>,
49 _mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>,
50}
51
52impl<'a> EventToken<'a> {
53 pub(crate) fn new(runner: &'a Runner<'a>, mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>) -> Self {
54 // Enable event receiving
55 runner.rx_event_channel.lock(|s| {
56 *s.borrow_mut() = Some(Signal::new());
57 });
58
59 Self {
60 runner: runner,
61 _mutex_guard: mutex_guard,
62 }
63 }
64}
65
66impl<'a> Future for EventToken<'a> {
67 type Output = MacEvent<'a>;
68
69 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
70 self.get_mut().runner.rx_event_channel.lock(|s| {
71 let signal = s.borrow_mut();
72 let signal = match &*signal {
73 Some(s) => s,
74 _ => unreachable!(),
75 };
76
77 let result = match signal.wait().poll_unpin(cx) {
78 Poll::Ready(mac_event) => Poll::Ready(mac_event),
79 Poll::Pending => Poll::Pending,
80 };
81
82 result
83 })
84 }
85}
86
87impl<'a> Drop for EventToken<'a> {
88 fn drop(&mut self) {
89 // Disable event receiving
90 // This will also drop the contained event, if it exists, and will free up receiving the next event
91 self.runner.rx_event_channel.lock(|s| {
92 *s.borrow_mut() = None;
93 });
94 }
95}
diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs
new file mode 100644
index 000000000..fffbb9edc
--- /dev/null
+++ b/embassy-stm32-wpan/src/mac/driver.rs
@@ -0,0 +1,122 @@
1#![allow(incomplete_features)]
2#![deny(unused_must_use)]
3
4use core::task::Context;
5
6use embassy_net_driver::{Capabilities, LinkState, Medium};
7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
8use embassy_sync::channel::Channel;
9
10use crate::mac::event::MacEvent;
11use crate::mac::runner::Runner;
12use crate::mac::MTU;
13
14pub struct Driver<'d> {
15 runner: &'d Runner<'d>,
16}
17
18impl<'d> Driver<'d> {
19 pub(crate) fn new(runner: &'d Runner<'d>) -> Self {
20 Self { runner: runner }
21 }
22}
23
24impl<'d> embassy_net_driver::Driver for Driver<'d> {
25 // type RxToken<'a> = RxToken<'a, 'd> where Self: 'a;
26 // type TxToken<'a> = TxToken<'a, 'd> where Self: 'a;
27 type RxToken<'a> = RxToken<'d> where Self: 'a;
28 type TxToken<'a> = TxToken<'d> where Self: 'a;
29
30 fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
31 if self.runner.rx_channel.poll_ready_to_receive(cx) && self.runner.tx_buf_channel.poll_ready_to_receive(cx) {
32 Some((
33 RxToken {
34 rx: &self.runner.rx_channel,
35 },
36 TxToken {
37 tx: &self.runner.tx_channel,
38 tx_buf: &self.runner.tx_buf_channel,
39 },
40 ))
41 } else {
42 None
43 }
44 }
45
46 fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> {
47 if self.runner.tx_buf_channel.poll_ready_to_receive(cx) {
48 Some(TxToken {
49 tx: &self.runner.tx_channel,
50 tx_buf: &self.runner.tx_buf_channel,
51 })
52 } else {
53 None
54 }
55 }
56
57 fn capabilities(&self) -> Capabilities {
58 let mut caps = Capabilities::default();
59 caps.max_transmission_unit = MTU;
60 // caps.max_burst_size = Some(self.tx.len());
61
62 caps.medium = Medium::Ieee802154;
63 caps
64 }
65
66 fn link_state(&mut self, _cx: &mut Context) -> LinkState {
67 // if self.phy.poll_link(&mut self.station_management, cx) {
68 // LinkState::Up
69 // } else {
70 // LinkState::Down
71 // }
72
73 LinkState::Down
74 }
75
76 fn ethernet_address(&self) -> [u8; 6] {
77 // self.mac_addr
78
79 [0; 6]
80 }
81}
82
83pub struct RxToken<'d> {
84 rx: &'d Channel<CriticalSectionRawMutex, MacEvent<'d>, 1>,
85}
86
87impl<'d> embassy_net_driver::RxToken for RxToken<'d> {
88 fn consume<R, F>(self, f: F) -> R
89 where
90 F: FnOnce(&mut [u8]) -> R,
91 {
92 // Only valid data events should be put into the queue
93
94 let data_event = match self.rx.try_recv().unwrap() {
95 MacEvent::McpsDataInd(data_event) => data_event,
96 _ => unreachable!(),
97 };
98
99 f(&mut data_event.payload())
100 }
101}
102
103pub struct TxToken<'d> {
104 tx: &'d Channel<CriticalSectionRawMutex, (&'d mut [u8; MTU], usize), 5>,
105 tx_buf: &'d Channel<CriticalSectionRawMutex, &'d mut [u8; MTU], 5>,
106}
107
108impl<'d> embassy_net_driver::TxToken for TxToken<'d> {
109 fn consume<R, F>(self, len: usize, f: F) -> R
110 where
111 F: FnOnce(&mut [u8]) -> R,
112 {
113 // Only valid tx buffers should be put into the queue
114 let buf = self.tx_buf.try_recv().unwrap();
115 let r = f(&mut buf[..len]);
116
117 // The tx channel should always be of equal capacity to the tx_buf channel
118 self.tx.try_send((buf, len)).unwrap();
119
120 r
121 }
122}
diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs
index a2bb79222..9ca4f5a2a 100644
--- a/embassy-stm32-wpan/src/mac/event.rs
+++ b/embassy-stm32-wpan/src/mac/event.rs
@@ -1,4 +1,4 @@
1use core::mem; 1use core::{mem, ptr};
2 2
3use super::indications::{ 3use super::indications::{
4 AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication, 4 AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication,
@@ -8,9 +8,9 @@ use super::responses::{
8 AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm, 8 AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm,
9 PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm, 9 PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm,
10}; 10};
11use crate::evt::EvtBox; 11use crate::evt::{EvtBox, MemoryManager};
12use crate::mac::opcodes::OpcodeM0ToM4; 12use crate::mac::opcodes::OpcodeM0ToM4;
13use crate::sub::mac::Mac; 13use crate::sub::mac::{self, Mac};
14 14
15pub(crate) trait ParseableMacEvent: Sized { 15pub(crate) trait ParseableMacEvent: Sized {
16 fn from_buffer<'a>(buf: &'a [u8]) -> Result<&'a Self, ()> { 16 fn from_buffer<'a>(buf: &'a [u8]) -> Result<&'a Self, ()> {
@@ -22,59 +22,8 @@ pub(crate) trait ParseableMacEvent: Sized {
22 } 22 }
23} 23}
24 24
25pub struct Event {
26 event_box: EvtBox<Mac>,
27}
28
29impl Event {
30 pub(crate) fn new(event_box: EvtBox<Mac>) -> Self {
31 Self { event_box }
32 }
33
34 pub fn mac_event<'a>(&'a self) -> Result<MacEvent<'a>, ()> {
35 let payload = self.event_box.payload();
36 let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap());
37
38 let opcode = OpcodeM0ToM4::try_from(opcode)?;
39 let buf = &payload[2..];
40
41 match opcode {
42 OpcodeM0ToM4::MlmeAssociateCnf => Ok(MacEvent::MlmeAssociateCnf(AssociateConfirm::from_buffer(buf)?)),
43 OpcodeM0ToM4::MlmeDisassociateCnf => {
44 Ok(MacEvent::MlmeDisassociateCnf(DisassociateConfirm::from_buffer(buf)?))
45 }
46 OpcodeM0ToM4::MlmeGetCnf => Ok(MacEvent::MlmeGetCnf(GetConfirm::from_buffer(buf)?)),
47 OpcodeM0ToM4::MlmeGtsCnf => Ok(MacEvent::MlmeGtsCnf(GtsConfirm::from_buffer(buf)?)),
48 OpcodeM0ToM4::MlmeResetCnf => Ok(MacEvent::MlmeResetCnf(ResetConfirm::from_buffer(buf)?)),
49 OpcodeM0ToM4::MlmeRxEnableCnf => Ok(MacEvent::MlmeRxEnableCnf(RxEnableConfirm::from_buffer(buf)?)),
50 OpcodeM0ToM4::MlmeScanCnf => Ok(MacEvent::MlmeScanCnf(ScanConfirm::from_buffer(buf)?)),
51 OpcodeM0ToM4::MlmeSetCnf => Ok(MacEvent::MlmeSetCnf(SetConfirm::from_buffer(buf)?)),
52 OpcodeM0ToM4::MlmeStartCnf => Ok(MacEvent::MlmeStartCnf(StartConfirm::from_buffer(buf)?)),
53 OpcodeM0ToM4::MlmePollCnf => Ok(MacEvent::MlmePollCnf(PollConfirm::from_buffer(buf)?)),
54 OpcodeM0ToM4::MlmeDpsCnf => Ok(MacEvent::MlmeDpsCnf(DpsConfirm::from_buffer(buf)?)),
55 OpcodeM0ToM4::MlmeSoundingCnf => Ok(MacEvent::MlmeSoundingCnf(SoundingConfirm::from_buffer(buf)?)),
56 OpcodeM0ToM4::MlmeCalibrateCnf => Ok(MacEvent::MlmeCalibrateCnf(CalibrateConfirm::from_buffer(buf)?)),
57 OpcodeM0ToM4::McpsDataCnf => Ok(MacEvent::McpsDataCnf(DataConfirm::from_buffer(buf)?)),
58 OpcodeM0ToM4::McpsPurgeCnf => Ok(MacEvent::McpsPurgeCnf(PurgeConfirm::from_buffer(buf)?)),
59 OpcodeM0ToM4::MlmeAssociateInd => Ok(MacEvent::MlmeAssociateInd(AssociateIndication::from_buffer(buf)?)),
60 OpcodeM0ToM4::MlmeDisassociateInd => {
61 Ok(MacEvent::MlmeDisassociateInd(DisassociateIndication::from_buffer(buf)?))
62 }
63 OpcodeM0ToM4::MlmeBeaconNotifyInd => {
64 Ok(MacEvent::MlmeBeaconNotifyInd(BeaconNotifyIndication::from_buffer(buf)?))
65 }
66 OpcodeM0ToM4::MlmeCommStatusInd => Ok(MacEvent::MlmeCommStatusInd(CommStatusIndication::from_buffer(buf)?)),
67 OpcodeM0ToM4::MlmeGtsInd => Ok(MacEvent::MlmeGtsInd(GtsIndication::from_buffer(buf)?)),
68 OpcodeM0ToM4::MlmeOrphanInd => Ok(MacEvent::MlmeOrphanInd(OrphanIndication::from_buffer(buf)?)),
69 OpcodeM0ToM4::MlmeSyncLossInd => Ok(MacEvent::MlmeSyncLossInd(SyncLossIndication::from_buffer(buf)?)),
70 OpcodeM0ToM4::MlmeDpsInd => Ok(MacEvent::MlmeDpsInd(DpsIndication::from_buffer(buf)?)),
71 OpcodeM0ToM4::McpsDataInd => Ok(MacEvent::McpsDataInd(DataIndication::from_buffer(buf)?)),
72 OpcodeM0ToM4::MlmePollInd => Ok(MacEvent::MlmePollInd(PollIndication::from_buffer(buf)?)),
73 }
74 }
75}
76
77#[cfg_attr(feature = "defmt", derive(defmt::Format))] 25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26#[derive(Debug)]
78pub enum MacEvent<'a> { 27pub enum MacEvent<'a> {
79 MlmeAssociateCnf(&'a AssociateConfirm), 28 MlmeAssociateCnf(&'a AssociateConfirm),
80 MlmeDisassociateCnf(&'a DisassociateConfirm), 29 MlmeDisassociateCnf(&'a DisassociateConfirm),
@@ -102,3 +51,103 @@ pub enum MacEvent<'a> {
102 McpsDataInd(&'a DataIndication), 51 McpsDataInd(&'a DataIndication),
103 MlmePollInd(&'a PollIndication), 52 MlmePollInd(&'a PollIndication),
104} 53}
54
55impl<'a> MacEvent<'a> {
56 pub(crate) fn new(event_box: EvtBox<Mac>) -> Result<Self, ()> {
57 let payload = event_box.payload();
58 let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap());
59
60 let opcode = OpcodeM0ToM4::try_from(opcode)?;
61 let buf = &payload[2..];
62
63 // To avoid re-parsing the opcode, we store the result of the parse
64 // this requires use of unsafe because rust cannot assume that a reference will become
65 // invalid when the underlying result is moved. However, because we refer to a "heap"
66 // allocation, the underlying reference will not move until the struct is dropped.
67
68 let mac_event = match opcode {
69 OpcodeM0ToM4::MlmeAssociateCnf => {
70 MacEvent::MlmeAssociateCnf(unsafe { &*(AssociateConfirm::from_buffer(buf)? as *const _) })
71 }
72 OpcodeM0ToM4::MlmeDisassociateCnf => {
73 MacEvent::MlmeDisassociateCnf(unsafe { &*(DisassociateConfirm::from_buffer(buf)? as *const _) })
74 }
75 OpcodeM0ToM4::MlmeGetCnf => MacEvent::MlmeGetCnf(unsafe { &*(GetConfirm::from_buffer(buf)? as *const _) }),
76 OpcodeM0ToM4::MlmeGtsCnf => MacEvent::MlmeGtsCnf(unsafe { &*(GtsConfirm::from_buffer(buf)? as *const _) }),
77 OpcodeM0ToM4::MlmeResetCnf => {
78 MacEvent::MlmeResetCnf(unsafe { &*(ResetConfirm::from_buffer(buf)? as *const _) })
79 }
80 OpcodeM0ToM4::MlmeRxEnableCnf => {
81 MacEvent::MlmeRxEnableCnf(unsafe { &*(RxEnableConfirm::from_buffer(buf)? as *const _) })
82 }
83 OpcodeM0ToM4::MlmeScanCnf => {
84 MacEvent::MlmeScanCnf(unsafe { &*(ScanConfirm::from_buffer(buf)? as *const _) })
85 }
86 OpcodeM0ToM4::MlmeSetCnf => MacEvent::MlmeSetCnf(unsafe { &*(SetConfirm::from_buffer(buf)? as *const _) }),
87 OpcodeM0ToM4::MlmeStartCnf => {
88 MacEvent::MlmeStartCnf(unsafe { &*(StartConfirm::from_buffer(buf)? as *const _) })
89 }
90 OpcodeM0ToM4::MlmePollCnf => {
91 MacEvent::MlmePollCnf(unsafe { &*(PollConfirm::from_buffer(buf)? as *const _) })
92 }
93 OpcodeM0ToM4::MlmeDpsCnf => MacEvent::MlmeDpsCnf(unsafe { &*(DpsConfirm::from_buffer(buf)? as *const _) }),
94 OpcodeM0ToM4::MlmeSoundingCnf => {
95 MacEvent::MlmeSoundingCnf(unsafe { &*(SoundingConfirm::from_buffer(buf)? as *const _) })
96 }
97 OpcodeM0ToM4::MlmeCalibrateCnf => {
98 MacEvent::MlmeCalibrateCnf(unsafe { &*(CalibrateConfirm::from_buffer(buf)? as *const _) })
99 }
100 OpcodeM0ToM4::McpsDataCnf => {
101 MacEvent::McpsDataCnf(unsafe { &*(DataConfirm::from_buffer(buf)? as *const _) })
102 }
103 OpcodeM0ToM4::McpsPurgeCnf => {
104 MacEvent::McpsPurgeCnf(unsafe { &*(PurgeConfirm::from_buffer(buf)? as *const _) })
105 }
106 OpcodeM0ToM4::MlmeAssociateInd => {
107 MacEvent::MlmeAssociateInd(unsafe { &*(AssociateIndication::from_buffer(buf)? as *const _) })
108 }
109 OpcodeM0ToM4::MlmeDisassociateInd => {
110 MacEvent::MlmeDisassociateInd(unsafe { &*(DisassociateIndication::from_buffer(buf)? as *const _) })
111 }
112 OpcodeM0ToM4::MlmeBeaconNotifyInd => {
113 MacEvent::MlmeBeaconNotifyInd(unsafe { &*(BeaconNotifyIndication::from_buffer(buf)? as *const _) })
114 }
115 OpcodeM0ToM4::MlmeCommStatusInd => {
116 MacEvent::MlmeCommStatusInd(unsafe { &*(CommStatusIndication::from_buffer(buf)? as *const _) })
117 }
118 OpcodeM0ToM4::MlmeGtsInd => {
119 MacEvent::MlmeGtsInd(unsafe { &*(GtsIndication::from_buffer(buf)? as *const _) })
120 }
121 OpcodeM0ToM4::MlmeOrphanInd => {
122 MacEvent::MlmeOrphanInd(unsafe { &*(OrphanIndication::from_buffer(buf)? as *const _) })
123 }
124 OpcodeM0ToM4::MlmeSyncLossInd => {
125 MacEvent::MlmeSyncLossInd(unsafe { &*(SyncLossIndication::from_buffer(buf)? as *const _) })
126 }
127 OpcodeM0ToM4::MlmeDpsInd => {
128 MacEvent::MlmeDpsInd(unsafe { &*(DpsIndication::from_buffer(buf)? as *const _) })
129 }
130 OpcodeM0ToM4::McpsDataInd => {
131 MacEvent::McpsDataInd(unsafe { &*(DataIndication::from_buffer(buf)? as *const _) })
132 }
133 OpcodeM0ToM4::MlmePollInd => {
134 MacEvent::MlmePollInd(unsafe { &*(PollIndication::from_buffer(buf)? as *const _) })
135 }
136 };
137
138 // Forget the event box so that drop isn't called
139 // We want to handle the lifetime ourselves
140
141 mem::forget(event_box);
142
143 Ok(mac_event)
144 }
145}
146
147unsafe impl<'a> Send for MacEvent<'a> {}
148
149impl<'a> Drop for MacEvent<'a> {
150 fn drop(&mut self) {
151 unsafe { mac::Mac::drop_event_packet(ptr::null_mut()) };
152 }
153}
diff --git a/embassy-stm32-wpan/src/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs
index 5445fb4af..c0b86d745 100644
--- a/embassy-stm32-wpan/src/mac/indications.rs
+++ b/embassy-stm32-wpan/src/mac/indications.rs
@@ -10,6 +10,7 @@ use super::typedefs::{
10/// MLME ASSOCIATE Indication which will be used by the MAC 10/// MLME ASSOCIATE Indication which will be used by the MAC
11/// to indicate the reception of an association request command 11/// to indicate the reception of an association request command
12#[repr(C)] 12#[repr(C)]
13#[derive(Debug)]
13#[cfg_attr(feature = "defmt", derive(defmt::Format))] 14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
14pub struct AssociateIndication { 15pub struct AssociateIndication {
15 /// Extended address of the device requesting association 16 /// Extended address of the device requesting association
@@ -31,6 +32,7 @@ impl ParseableMacEvent for AssociateIndication {}
31/// MLME DISASSOCIATE indication which will be used to send 32/// MLME DISASSOCIATE indication which will be used to send
32/// disassociation indication to the application. 33/// disassociation indication to the application.
33#[repr(C)] 34#[repr(C)]
35#[derive(Debug)]
34#[cfg_attr(feature = "defmt", derive(defmt::Format))] 36#[cfg_attr(feature = "defmt", derive(defmt::Format))]
35pub struct DisassociateIndication { 37pub struct DisassociateIndication {
36 /// Extended address of the device requesting association 38 /// Extended address of the device requesting association
@@ -52,6 +54,7 @@ impl ParseableMacEvent for DisassociateIndication {}
52/// MLME BEACON NOTIIFY Indication which is used to send parameters contained 54/// MLME BEACON NOTIIFY Indication which is used to send parameters contained
53/// within a beacon frame received by the MAC to the application 55/// within a beacon frame received by the MAC to the application
54#[repr(C)] 56#[repr(C)]
57#[derive(Debug)]
55#[cfg_attr(feature = "defmt", derive(defmt::Format))] 58#[cfg_attr(feature = "defmt", derive(defmt::Format))]
56pub struct BeaconNotifyIndication { 59pub struct BeaconNotifyIndication {
57 /// he set of octets comprising the beacon payload to be transferred 60 /// he set of octets comprising the beacon payload to be transferred
@@ -73,6 +76,7 @@ impl ParseableMacEvent for BeaconNotifyIndication {}
73 76
74/// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status 77/// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status
75#[repr(C)] 78#[repr(C)]
79#[derive(Debug)]
76#[cfg_attr(feature = "defmt", derive(defmt::Format))] 80#[cfg_attr(feature = "defmt", derive(defmt::Format))]
77pub struct CommStatusIndication { 81pub struct CommStatusIndication {
78 /// The 16-bit PAN identifier of the device from which the frame 82 /// The 16-bit PAN identifier of the device from which the frame
@@ -103,6 +107,7 @@ impl ParseableMacEvent for CommStatusIndication {}
103/// MLME GTS Indication indicates that a GTS has been allocated or that a 107/// MLME GTS Indication indicates that a GTS has been allocated or that a
104/// previously allocated GTS has been deallocated 108/// previously allocated GTS has been deallocated
105#[repr(C)] 109#[repr(C)]
110#[derive(Debug)]
106#[cfg_attr(feature = "defmt", derive(defmt::Format))] 111#[cfg_attr(feature = "defmt", derive(defmt::Format))]
107pub struct GtsIndication { 112pub struct GtsIndication {
108 /// The short address of the device that has been allocated or deallocated a GTS 113 /// The short address of the device that has been allocated or deallocated a GTS
@@ -126,6 +131,7 @@ impl ParseableMacEvent for GtsIndication {}
126/// MLME ORPHAN Indication which is used by the coordinator to notify the 131/// MLME ORPHAN Indication which is used by the coordinator to notify the
127/// application of the presence of an orphaned device 132/// application of the presence of an orphaned device
128#[repr(C)] 133#[repr(C)]
134#[derive(Debug)]
129#[cfg_attr(feature = "defmt", derive(defmt::Format))] 135#[cfg_attr(feature = "defmt", derive(defmt::Format))]
130pub struct OrphanIndication { 136pub struct OrphanIndication {
131 /// Extended address of the orphaned device 137 /// Extended address of the orphaned device
@@ -147,6 +153,7 @@ impl ParseableMacEvent for OrphanIndication {}
147/// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss 153/// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss
148/// of synchronization with the coordinator 154/// of synchronization with the coordinator
149#[repr(C)] 155#[repr(C)]
156#[derive(Debug)]
150#[cfg_attr(feature = "defmt", derive(defmt::Format))] 157#[cfg_attr(feature = "defmt", derive(defmt::Format))]
151pub struct SyncLossIndication { 158pub struct SyncLossIndication {
152 /// The PAN identifier with which the device lost synchronization or to which it was realigned 159 /// The PAN identifier with which the device lost synchronization or to which it was realigned
@@ -172,6 +179,7 @@ impl ParseableMacEvent for SyncLossIndication {}
172/// MLME DPS Indication which indicates the expiration of the DPSIndexDuration 179/// MLME DPS Indication which indicates the expiration of the DPSIndexDuration
173/// and the resetting of the DPS values in the PHY 180/// and the resetting of the DPS values in the PHY
174#[repr(C)] 181#[repr(C)]
182#[derive(Debug)]
175#[cfg_attr(feature = "defmt", derive(defmt::Format))] 183#[cfg_attr(feature = "defmt", derive(defmt::Format))]
176pub struct DpsIndication { 184pub struct DpsIndication {
177 /// byte stuffing to keep 32 bit alignment 185 /// byte stuffing to keep 32 bit alignment
@@ -181,6 +189,7 @@ pub struct DpsIndication {
181impl ParseableMacEvent for DpsIndication {} 189impl ParseableMacEvent for DpsIndication {}
182 190
183#[repr(C)] 191#[repr(C)]
192#[derive(Debug)]
184#[cfg_attr(feature = "defmt", derive(defmt::Format))] 193#[cfg_attr(feature = "defmt", derive(defmt::Format))]
185pub struct DataIndication { 194pub struct DataIndication {
186 /// Pointer to the set of octets forming the MSDU being indicated 195 /// Pointer to the set of octets forming the MSDU being indicated
@@ -236,14 +245,15 @@ pub struct DataIndication {
236impl ParseableMacEvent for DataIndication {} 245impl ParseableMacEvent for DataIndication {}
237 246
238impl DataIndication { 247impl DataIndication {
239 pub fn payload<'a>(&'a self) -> &'a [u8] { 248 pub fn payload<'a>(&'a self) -> &'a mut [u8] {
240 unsafe { slice::from_raw_parts(self.msdu_ptr, self.msdu_length as usize) } 249 unsafe { slice::from_raw_parts_mut(self.msdu_ptr as *mut _, self.msdu_length as usize) }
241 } 250 }
242} 251}
243 252
244/// MLME POLL Indication which will be used for indicating the Data Request 253/// MLME POLL Indication which will be used for indicating the Data Request
245/// reception to upper layer as defined in Zigbee r22 - D.8.2 254/// reception to upper layer as defined in Zigbee r22 - D.8.2
246#[repr(C)] 255#[repr(C)]
256#[derive(Debug)]
247#[cfg_attr(feature = "defmt", derive(defmt::Format))] 257#[cfg_attr(feature = "defmt", derive(defmt::Format))]
248pub struct PollIndication { 258pub struct PollIndication {
249 /// addressing mode used 259 /// addressing mode used
diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs
index 8d5edad6b..c847a5cca 100644
--- a/embassy-stm32-wpan/src/mac/mod.rs
+++ b/embassy-stm32-wpan/src/mac/mod.rs
@@ -1,8 +1,21 @@
1pub mod commands; 1pub mod commands;
2mod consts; 2mod consts;
3pub mod control;
4mod driver;
3pub mod event; 5pub mod event;
4pub mod indications; 6pub mod indications;
5mod macros; 7mod macros;
6mod opcodes; 8mod opcodes;
7pub mod responses; 9pub mod responses;
10pub mod runner;
8pub mod typedefs; 11pub mod typedefs;
12
13pub use crate::mac::control::Control;
14use crate::mac::driver::Driver;
15pub use crate::mac::runner::Runner;
16
17const MTU: usize = 127;
18
19pub async fn new<'a>(runner: &'a Runner<'a>) -> (Control<'a>, Driver<'a>) {
20 (Control::new(runner), Driver::new(runner))
21}
diff --git a/embassy-stm32-wpan/src/mac/responses.rs b/embassy-stm32-wpan/src/mac/responses.rs
index 5d203084c..544fdaae8 100644
--- a/embassy-stm32-wpan/src/mac/responses.rs
+++ b/embassy-stm32-wpan/src/mac/responses.rs
@@ -8,6 +8,7 @@ use super::typedefs::{
8/// MLME ASSOCIATE Confirm used to inform of the initiating device whether 8/// MLME ASSOCIATE Confirm used to inform of the initiating device whether
9/// its request to associate was successful or unsuccessful 9/// its request to associate was successful or unsuccessful
10#[repr(C)] 10#[repr(C)]
11#[derive(Debug)]
11#[cfg_attr(feature = "defmt", derive(defmt::Format))] 12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
12pub struct AssociateConfirm { 13pub struct AssociateConfirm {
13 /// short address allocated by the coordinator on successful association 14 /// short address allocated by the coordinator on successful association
@@ -30,6 +31,7 @@ impl ParseableMacEvent for AssociateConfirm {}
30 31
31/// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application. 32/// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application.
32#[repr(C)] 33#[repr(C)]
34#[derive(Debug)]
33#[cfg_attr(feature = "defmt", derive(defmt::Format))] 35#[cfg_attr(feature = "defmt", derive(defmt::Format))]
34pub struct DisassociateConfirm { 36pub struct DisassociateConfirm {
35 /// status of the disassociation attempt 37 /// status of the disassociation attempt
@@ -46,6 +48,7 @@ impl ParseableMacEvent for DisassociateConfirm {}
46 48
47/// MLME GET Confirm which requests information about a given PIB attribute 49/// MLME GET Confirm which requests information about a given PIB attribute
48#[repr(C)] 50#[repr(C)]
51#[derive(Debug)]
49#[cfg_attr(feature = "defmt", derive(defmt::Format))] 52#[cfg_attr(feature = "defmt", derive(defmt::Format))]
50pub struct GetConfirm { 53pub struct GetConfirm {
51 /// The pointer to the value of the PIB attribute attempted to read 54 /// The pointer to the value of the PIB attribute attempted to read
@@ -65,6 +68,7 @@ impl ParseableMacEvent for GetConfirm {}
65/// MLME GTS Confirm which eports the results of a request to allocate a new GTS 68/// MLME GTS Confirm which eports the results of a request to allocate a new GTS
66/// or to deallocate an existing GTS 69/// or to deallocate an existing GTS
67#[repr(C)] 70#[repr(C)]
71#[derive(Debug)]
68#[cfg_attr(feature = "defmt", derive(defmt::Format))] 72#[cfg_attr(feature = "defmt", derive(defmt::Format))]
69pub struct GtsConfirm { 73pub struct GtsConfirm {
70 /// The characteristics of the GTS 74 /// The characteristics of the GTS
@@ -79,10 +83,11 @@ impl ParseableMacEvent for GtsConfirm {}
79 83
80/// MLME RESET Confirm which is used to report the results of the reset operation 84/// MLME RESET Confirm which is used to report the results of the reset operation
81#[repr(C)] 85#[repr(C)]
86#[derive(Debug)]
82#[cfg_attr(feature = "defmt", derive(defmt::Format))] 87#[cfg_attr(feature = "defmt", derive(defmt::Format))]
83pub struct ResetConfirm { 88pub struct ResetConfirm {
84 /// The result of the reset operation 89 /// The result of the reset operation
85 status: MacStatus, 90 pub status: MacStatus,
86 /// byte stuffing to keep 32 bit alignment 91 /// byte stuffing to keep 32 bit alignment
87 a_stuffing: [u8; 3], 92 a_stuffing: [u8; 3],
88} 93}
@@ -92,10 +97,11 @@ impl ParseableMacEvent for ResetConfirm {}
92/// MLME RX ENABLE Confirm which is used to report the results of the attempt 97/// MLME RX ENABLE Confirm which is used to report the results of the attempt
93/// to enable or disable the receiver 98/// to enable or disable the receiver
94#[repr(C)] 99#[repr(C)]
100#[derive(Debug)]
95#[cfg_attr(feature = "defmt", derive(defmt::Format))] 101#[cfg_attr(feature = "defmt", derive(defmt::Format))]
96pub struct RxEnableConfirm { 102pub struct RxEnableConfirm {
97 /// Result of the request to enable or disable the receiver 103 /// Result of the request to enable or disable the receiver
98 status: MacStatus, 104 pub status: MacStatus,
99 /// byte stuffing to keep 32 bit alignment 105 /// byte stuffing to keep 32 bit alignment
100 a_stuffing: [u8; 3], 106 a_stuffing: [u8; 3],
101} 107}
@@ -104,6 +110,7 @@ impl ParseableMacEvent for RxEnableConfirm {}
104 110
105/// MLME SCAN Confirm which is used to report the result of the channel scan request 111/// MLME SCAN Confirm which is used to report the result of the channel scan request
106#[repr(C)] 112#[repr(C)]
113#[derive(Debug)]
107#[cfg_attr(feature = "defmt", derive(defmt::Format))] 114#[cfg_attr(feature = "defmt", derive(defmt::Format))]
108pub struct ScanConfirm { 115pub struct ScanConfirm {
109 /// Status of the scan request 116 /// Status of the scan request
@@ -130,6 +137,7 @@ impl ParseableMacEvent for ScanConfirm {}
130 137
131/// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute 138/// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute
132#[repr(C)] 139#[repr(C)]
140#[derive(Debug)]
133#[cfg_attr(feature = "defmt", derive(defmt::Format))] 141#[cfg_attr(feature = "defmt", derive(defmt::Format))]
134pub struct SetConfirm { 142pub struct SetConfirm {
135 /// The result of the set operation 143 /// The result of the set operation
@@ -145,6 +153,7 @@ impl ParseableMacEvent for SetConfirm {}
145/// MLME START Confirm which is used to report the results of the attempt to 153/// MLME START Confirm which is used to report the results of the attempt to
146/// start using a new superframe configuration 154/// start using a new superframe configuration
147#[repr(C)] 155#[repr(C)]
156#[derive(Debug)]
148#[cfg_attr(feature = "defmt", derive(defmt::Format))] 157#[cfg_attr(feature = "defmt", derive(defmt::Format))]
149pub struct StartConfirm { 158pub struct StartConfirm {
150 /// Result of the attempt to start using an updated superframe configuration 159 /// Result of the attempt to start using an updated superframe configuration
@@ -157,6 +166,7 @@ impl ParseableMacEvent for StartConfirm {}
157 166
158/// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data 167/// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data
159#[repr(C)] 168#[repr(C)]
169#[derive(Debug)]
160#[cfg_attr(feature = "defmt", derive(defmt::Format))] 170#[cfg_attr(feature = "defmt", derive(defmt::Format))]
161pub struct PollConfirm { 171pub struct PollConfirm {
162 /// The status of the data request 172 /// The status of the data request
@@ -169,6 +179,7 @@ impl ParseableMacEvent for PollConfirm {}
169 179
170/// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS 180/// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS
171#[repr(C)] 181#[repr(C)]
182#[derive(Debug)]
172#[cfg_attr(feature = "defmt", derive(defmt::Format))] 183#[cfg_attr(feature = "defmt", derive(defmt::Format))]
173pub struct DpsConfirm { 184pub struct DpsConfirm {
174 /// The status of the DPS request 185 /// The status of the DPS request
@@ -182,10 +193,11 @@ impl ParseableMacEvent for DpsConfirm {}
182/// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide 193/// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide
183/// channel sounding information 194/// channel sounding information
184#[repr(C)] 195#[repr(C)]
196#[derive(Debug)]
185#[cfg_attr(feature = "defmt", derive(defmt::Format))] 197#[cfg_attr(feature = "defmt", derive(defmt::Format))]
186pub struct SoundingConfirm { 198pub struct SoundingConfirm {
187 /// Results of the sounding measurement 199 /// Results of the sounding measurement
188 sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED], 200 pub sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED],
189 201
190 status: u8, 202 status: u8,
191} 203}
@@ -195,6 +207,7 @@ impl ParseableMacEvent for SoundingConfirm {}
195/// MLME CALIBRATE Confirm which reports the result of a request to the PHY 207/// MLME CALIBRATE Confirm which reports the result of a request to the PHY
196/// to provide internal propagation path information 208/// to provide internal propagation path information
197#[repr(C)] 209#[repr(C)]
210#[derive(Debug)]
198#[cfg_attr(feature = "defmt", derive(defmt::Format))] 211#[cfg_attr(feature = "defmt", derive(defmt::Format))]
199pub struct CalibrateConfirm { 212pub struct CalibrateConfirm {
200 /// The status of the attempt to return sounding data 213 /// The status of the attempt to return sounding data
@@ -214,6 +227,7 @@ impl ParseableMacEvent for CalibrateConfirm {}
214/// MCPS DATA Confirm which will be used for reporting the results of 227/// MCPS DATA Confirm which will be used for reporting the results of
215/// MAC data related requests from the application 228/// MAC data related requests from the application
216#[repr(C)] 229#[repr(C)]
230#[derive(Debug)]
217#[cfg_attr(feature = "defmt", derive(defmt::Format))] 231#[cfg_attr(feature = "defmt", derive(defmt::Format))]
218pub struct DataConfirm { 232pub struct DataConfirm {
219 /// The handle associated with the MSDU being confirmed 233 /// The handle associated with the MSDU being confirmed
@@ -245,6 +259,7 @@ impl ParseableMacEvent for DataConfirm {}
245/// MCPS PURGE Confirm which will be used by the MAC to notify the application of 259/// MCPS PURGE Confirm which will be used by the MAC to notify the application of
246/// the status of its request to purge an MSDU from the transaction queue 260/// the status of its request to purge an MSDU from the transaction queue
247#[repr(C)] 261#[repr(C)]
262#[derive(Debug)]
248#[cfg_attr(feature = "defmt", derive(defmt::Format))] 263#[cfg_attr(feature = "defmt", derive(defmt::Format))]
249pub struct PurgeConfirm { 264pub struct PurgeConfirm {
250 /// Handle associated with the MSDU requested to be purged from the transaction queue 265 /// Handle associated with the MSDU requested to be purged from the transaction queue
diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs
new file mode 100644
index 000000000..1be6df8a4
--- /dev/null
+++ b/embassy-stm32-wpan/src/mac/runner.rs
@@ -0,0 +1,109 @@
1use core::cell::RefCell;
2
3use embassy_futures::join;
4use embassy_sync::blocking_mutex;
5use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
6use embassy_sync::channel::Channel;
7use embassy_sync::mutex::Mutex;
8use embassy_sync::signal::Signal;
9
10use crate::mac::commands::DataRequest;
11use crate::mac::event::MacEvent;
12use crate::mac::typedefs::{AddressMode, MacAddress, PanId, SecurityLevel};
13use crate::mac::MTU;
14use crate::sub::mac::Mac;
15
16type ZeroCopyPubSub<M, T> = blocking_mutex::Mutex<M, RefCell<Option<Signal<NoopRawMutex, T>>>>;
17
18pub struct Runner<'a> {
19 pub(crate) mac_subsystem: Mac,
20 // rx event backpressure is already provided through the MacEvent drop mechanism
21 // therefore, we don't need to worry about overwriting events
22 pub(crate) rx_event_channel: ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>,
23 pub(crate) read_mutex: Mutex<CriticalSectionRawMutex, ()>,
24 pub(crate) write_mutex: Mutex<CriticalSectionRawMutex, ()>,
25 pub(crate) rx_channel: Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>,
26 pub(crate) tx_channel: Channel<CriticalSectionRawMutex, (&'a mut [u8; MTU], usize), 5>,
27 pub(crate) tx_buf_channel: Channel<CriticalSectionRawMutex, &'a mut [u8; MTU], 5>,
28}
29
30impl<'a> Runner<'a> {
31 pub fn new(mac: Mac, tx_buf_queue: [&'a mut [u8; MTU]; 5]) -> Self {
32 let this = Self {
33 mac_subsystem: mac,
34 rx_event_channel: blocking_mutex::Mutex::new(RefCell::new(None)),
35 read_mutex: Mutex::new(()),
36 write_mutex: Mutex::new(()),
37 rx_channel: Channel::new(),
38 tx_channel: Channel::new(),
39 tx_buf_channel: Channel::new(),
40 };
41
42 for buf in tx_buf_queue {
43 this.tx_buf_channel.try_send(buf).unwrap();
44 }
45
46 this
47 }
48
49 pub async fn run(&'a self) -> ! {
50 join::join(
51 async {
52 loop {
53 if let Ok(mac_event) = self.mac_subsystem.read().await {
54 match mac_event {
55 MacEvent::McpsDataInd(_) => {
56 self.rx_channel.send(mac_event).await;
57 }
58 _ => {
59 self.rx_event_channel.lock(|s| {
60 match &*s.borrow() {
61 Some(signal) => {
62 signal.signal(mac_event);
63 }
64 None => {}
65 };
66 });
67 }
68 }
69 }
70 }
71 },
72 async {
73 let mut msdu_handle = 0x02;
74
75 loop {
76 let (buf, len) = self.tx_channel.recv().await;
77 let _wm = self.write_mutex.lock().await;
78
79 // The mutex should be dropped on the next loop iteration
80 self.mac_subsystem
81 .send_command(
82 DataRequest {
83 src_addr_mode: AddressMode::Short,
84 dst_addr_mode: AddressMode::Short,
85 dst_pan_id: PanId([0x1A, 0xAA]),
86 dst_address: MacAddress::BROADCAST,
87 msdu_handle: msdu_handle,
88 ack_tx: 0x00,
89 gts_tx: false,
90 security_level: SecurityLevel::Unsecure,
91 ..Default::default()
92 }
93 .set_buffer(&buf[..len]),
94 )
95 .await
96 .unwrap();
97
98 msdu_handle = msdu_handle.wrapping_add(1);
99
100 // The tx channel should always be of equal capacity to the tx_buf channel
101 self.tx_buf_channel.try_send(buf).unwrap();
102 }
103 },
104 )
105 .await;
106
107 loop {}
108 }
109}
diff --git a/embassy-stm32-wpan/src/mac/typedefs.rs b/embassy-stm32-wpan/src/mac/typedefs.rs
index 98c67c86b..0552b8ea1 100644
--- a/embassy-stm32-wpan/src/mac/typedefs.rs
+++ b/embassy-stm32-wpan/src/mac/typedefs.rs
@@ -1,3 +1,5 @@
1use core::fmt::Debug;
2
1use crate::numeric_enum; 3use crate::numeric_enum;
2 4
3#[derive(Debug)] 5#[derive(Debug)]
@@ -37,7 +39,7 @@ numeric_enum! {
37numeric_enum! { 39numeric_enum! {
38 #[repr(u8)] 40 #[repr(u8)]
39 /// this enum contains all the MAC PIB Ids 41 /// this enum contains all the MAC PIB Ids
40 #[derive(Default)] 42 #[derive(Default, Debug)]
41 #[cfg_attr(feature = "defmt", derive(defmt::Format))] 43 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
42 pub enum PibId { 44 pub enum PibId {
43 // PHY 45 // PHY
@@ -96,7 +98,7 @@ numeric_enum! {
96 98
97numeric_enum! { 99numeric_enum! {
98 #[repr(u8)] 100 #[repr(u8)]
99 #[derive(Default, Clone, Copy)] 101 #[derive(Default, Clone, Copy, Debug)]
100 #[cfg_attr(feature = "defmt", derive(defmt::Format))] 102 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
101 pub enum AddressMode { 103 pub enum AddressMode {
102 #[default] 104 #[default]
@@ -113,6 +115,18 @@ pub union MacAddress {
113 pub extended: [u8; 8], 115 pub extended: [u8; 8],
114} 116}
115 117
118impl Debug for MacAddress {
119 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
120 unsafe {
121 write!(
122 fmt,
123 "MacAddress {{ short: {:?}, extended: {:?} }}",
124 self.short, self.extended
125 )
126 }
127 }
128}
129
116#[cfg(feature = "defmt")] 130#[cfg(feature = "defmt")]
117impl defmt::Format for MacAddress { 131impl defmt::Format for MacAddress {
118 fn format(&self, fmt: defmt::Formatter) { 132 fn format(&self, fmt: defmt::Formatter) {
@@ -159,7 +173,7 @@ pub struct GtsCharacteristics {
159 173
160/// MAC PAN Descriptor which contains the network details of the device from 174/// MAC PAN Descriptor which contains the network details of the device from
161/// which the beacon is received 175/// which the beacon is received
162#[derive(Default, Clone, Copy)] 176#[derive(Default, Clone, Copy, Debug)]
163#[cfg_attr(feature = "defmt", derive(defmt::Format))] 177#[cfg_attr(feature = "defmt", derive(defmt::Format))]
164pub struct PanDescriptor { 178pub struct PanDescriptor {
165 /// PAN identifier of the coordinator 179 /// PAN identifier of the coordinator
@@ -223,7 +237,7 @@ impl TryFrom<&[u8]> for PanDescriptor {
223 237
224numeric_enum! { 238numeric_enum! {
225 #[repr(u8)] 239 #[repr(u8)]
226 #[derive(Default, Clone, Copy)] 240 #[derive(Default, Clone, Copy, Debug)]
227 #[cfg_attr(feature = "defmt", derive(defmt::Format))] 241 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
228 /// Building wireless applications with STM32WB series MCUs - Application note 13.10.3 242 /// Building wireless applications with STM32WB series MCUs - Application note 13.10.3
229 pub enum MacChannel { 243 pub enum MacChannel {
@@ -289,7 +303,7 @@ defmt::bitflags! {
289 303
290numeric_enum! { 304numeric_enum! {
291 #[repr(u8)] 305 #[repr(u8)]
292 #[derive(Default, Clone, Copy)] 306 #[derive(Default, Clone, Copy, Debug)]
293 #[cfg_attr(feature = "defmt", derive(defmt::Format))] 307 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
294 pub enum KeyIdMode { 308 pub enum KeyIdMode {
295 #[default] 309 #[default]
@@ -306,6 +320,7 @@ numeric_enum! {
306 320
307numeric_enum! { 321numeric_enum! {
308 #[repr(u8)] 322 #[repr(u8)]
323 #[derive(Debug)]
309 #[cfg_attr(feature = "defmt", derive(defmt::Format))] 324 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
310 pub enum AssociationStatus { 325 pub enum AssociationStatus {
311 /// Association successful 326 /// Association successful
@@ -319,7 +334,7 @@ numeric_enum! {
319 334
320numeric_enum! { 335numeric_enum! {
321 #[repr(u8)] 336 #[repr(u8)]
322 #[derive(Clone, Copy)] 337 #[derive(Clone, Copy, Debug)]
323 #[cfg_attr(feature = "defmt", derive(defmt::Format))] 338 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
324 pub enum DisassociationReason { 339 pub enum DisassociationReason {
325 /// The coordinator wishes the device to leave the PAN. 340 /// The coordinator wishes the device to leave the PAN.
@@ -331,7 +346,7 @@ numeric_enum! {
331 346
332numeric_enum! { 347numeric_enum! {
333 #[repr(u8)] 348 #[repr(u8)]
334 #[derive(Default, Clone, Copy)] 349 #[derive(Default, Clone, Copy, Debug)]
335 #[cfg_attr(feature = "defmt", derive(defmt::Format))] 350 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
336 pub enum SecurityLevel { 351 pub enum SecurityLevel {
337 /// MAC Unsecured Mode Security 352 /// MAC Unsecured Mode Security
@@ -346,6 +361,7 @@ numeric_enum! {
346 361
347numeric_enum! { 362numeric_enum! {
348 #[repr(u8)] 363 #[repr(u8)]
364 #[derive(Debug)]
349 #[cfg_attr(feature = "defmt", derive(defmt::Format))] 365 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
350 pub enum ScanType { 366 pub enum ScanType {
351 EdScan = 0x00, 367 EdScan = 0x00,
@@ -356,7 +372,7 @@ numeric_enum! {
356} 372}
357 373
358/// newtype for Pan Id 374/// newtype for Pan Id
359#[derive(Default, Clone, Copy)] 375#[derive(Default, Clone, Copy, Debug)]
360#[cfg_attr(feature = "defmt", derive(defmt::Format))] 376#[cfg_attr(feature = "defmt", derive(defmt::Format))]
361pub struct PanId(pub [u8; 2]); 377pub struct PanId(pub [u8; 2]);
362 378
diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs
index d9bf4c909..b0cf0248a 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;
12use crate::consts::TlPacketType; 12use crate::consts::TlPacketType;
13use crate::evt::{EvtBox, EvtPacket}; 13use crate::evt::{EvtBox, EvtPacket};
14use crate::mac::commands::MacCommand; 14use crate::mac::commands::MacCommand;
15use crate::mac::event::Event; 15use crate::mac::event::MacEvent;
16use crate::mac::typedefs::MacError; 16use crate::mac::typedefs::MacError;
17use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; 17use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER};
18use crate::{channels, evt}; 18use crate::{channels, evt};
@@ -94,14 +94,16 @@ impl Mac {
94 } 94 }
95 } 95 }
96 96
97 pub async fn read(&self) -> Event { 97 pub async fn read(&self) -> Result<MacEvent<'_>, ()> {
98 Event::new(self.tl_read().await) 98 MacEvent::new(self.tl_read().await)
99 } 99 }
100} 100}
101 101
102impl evt::MemoryManager for Mac { 102impl evt::MemoryManager for Mac {
103 /// SAFETY: passing a pointer to something other than a managed event packet is UB 103 /// SAFETY: passing a pointer to something other than a managed event packet is UB
104 unsafe fn drop_event_packet(_: *mut EvtPacket) { 104 unsafe fn drop_event_packet(_: *mut EvtPacket) {
105 trace!("mac drop event");
106
105 // Write the ack 107 // Write the ack
106 CmdPacket::write_into( 108 CmdPacket::write_into(
107 MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _, 109 MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _,
@@ -111,7 +113,7 @@ impl evt::MemoryManager for Mac {
111 ); 113 );
112 114
113 // Clear the rx flag 115 // Clear the rx flag
114 let _ = poll_once(Ipcc::receive::<bool>( 116 let _ = poll_once(Ipcc::receive::<()>(
115 channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, 117 channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL,
116 || None, 118 || None,
117 )); 119 ));
diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs
index 77352874d..f421af392 100644
--- a/embassy-sync/src/channel.rs
+++ b/embassy-sync/src/channel.rs
@@ -335,6 +335,12 @@ impl<T, const N: usize> ChannelState<T, N> {
335 } 335 }
336 } 336 }
337 337
338 fn poll_ready_to_receive(&mut self, cx: &mut Context<'_>) -> bool {
339 self.receiver_waker.register(cx.waker());
340
341 !self.queue.is_empty()
342 }
343
338 fn try_send(&mut self, message: T) -> Result<(), TrySendError<T>> { 344 fn try_send(&mut self, message: T) -> Result<(), TrySendError<T>> {
339 self.try_send_with_context(message, None) 345 self.try_send_with_context(message, None)
340 } 346 }
@@ -353,6 +359,12 @@ impl<T, const N: usize> ChannelState<T, N> {
353 } 359 }
354 } 360 }
355 } 361 }
362
363 fn poll_ready_to_send(&mut self, cx: &mut Context<'_>) -> bool {
364 self.senders_waker.register(cx.waker());
365
366 !self.queue.is_full()
367 }
356} 368}
357 369
358/// A bounded channel for communicating between asynchronous tasks 370/// A bounded channel for communicating between asynchronous tasks
@@ -401,6 +413,16 @@ where
401 self.lock(|c| c.try_send_with_context(m, cx)) 413 self.lock(|c| c.try_send_with_context(m, cx))
402 } 414 }
403 415
416 /// Allows a poll_fn to poll until the channel is ready to receive
417 pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool {
418 self.lock(|c| c.poll_ready_to_receive(cx))
419 }
420
421 /// Allows a poll_fn to poll until the channel is ready to send
422 pub fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> bool {
423 self.lock(|c| c.poll_ready_to_send(cx))
424 }
425
404 /// Get a sender for this channel. 426 /// Get a sender for this channel.
405 pub fn sender(&self) -> Sender<'_, M, T, N> { 427 pub fn sender(&self) -> Sender<'_, M, T, N> {
406 Sender { channel: self } 428 Sender { channel: self }
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml
index becf2d3fb..7c0b83e65 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
10embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 10embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] }
12embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } 12embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] }
13embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ieee802154", "nightly"], optional=true }
13 14
14defmt = "0.3" 15defmt = "0.3"
15defmt-rtt = "0.4" 16defmt-rtt = "0.4"
@@ -20,11 +21,11 @@ embedded-hal = "0.2.6"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 21panic-probe = { version = "0.3", features = ["print-defmt"] }
21futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 22futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
22heapless = { version = "0.7.5", default-features = false } 23heapless = { version = "0.7.5", default-features = false }
23 24static_cell = { version = "1.1", features = ["nightly"]}
24 25
25[features] 26[features]
26default = ["ble", "mac"] 27default = ["ble", "mac"]
27mac = ["embassy-stm32-wpan/mac"] 28mac = ["embassy-stm32-wpan/mac", "dep:embassy-net"]
28ble = ["embassy-stm32-wpan/ble"] 29ble = ["embassy-stm32-wpan/ble"]
29 30
30[[bin]] 31[[bin]]
@@ -40,6 +41,10 @@ name = "mac_ffd"
40required-features = ["mac"] 41required-features = ["mac"]
41 42
42[[bin]] 43[[bin]]
44name = "mac_ffd_net"
45required-features = ["mac"]
46
47[[bin]]
43name = "eddystone_beacon" 48name = "eddystone_beacon"
44required-features = ["ble"] 49required-features = ["ble"]
45 50
diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs
index bc71e29aa..1379ac6ba 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) {
73 }) 73 })
74 .await 74 .await
75 .unwrap(); 75 .unwrap();
76 { 76 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
77 let evt = mbox.mac_subsystem.read().await;
78 defmt::info!("{:#x}", evt.mac_event());
79 }
80 77
81 info!("setting extended address"); 78 info!("setting extended address");
82 let extended_address: u64 = 0xACDE480000000001; 79 let extended_address: u64 = 0xACDE480000000001;
@@ -87,10 +84,7 @@ async fn main(spawner: Spawner) {
87 }) 84 })
88 .await 85 .await
89 .unwrap(); 86 .unwrap();
90 { 87 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
91 let evt = mbox.mac_subsystem.read().await;
92 defmt::info!("{:#x}", evt.mac_event());
93 }
94 88
95 info!("setting short address"); 89 info!("setting short address");
96 let short_address: u16 = 0x1122; 90 let short_address: u16 = 0x1122;
@@ -101,10 +95,7 @@ async fn main(spawner: Spawner) {
101 }) 95 })
102 .await 96 .await
103 .unwrap(); 97 .unwrap();
104 { 98 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
105 let evt = mbox.mac_subsystem.read().await;
106 defmt::info!("{:#x}", evt.mac_event());
107 }
108 99
109 info!("setting association permit"); 100 info!("setting association permit");
110 let association_permit: bool = true; 101 let association_permit: bool = true;
@@ -115,10 +106,7 @@ async fn main(spawner: Spawner) {
115 }) 106 })
116 .await 107 .await
117 .unwrap(); 108 .unwrap();
118 { 109 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
119 let evt = mbox.mac_subsystem.read().await;
120 defmt::info!("{:#x}", evt.mac_event());
121 }
122 110
123 info!("setting TX power"); 111 info!("setting TX power");
124 let transmit_power: i8 = 2; 112 let transmit_power: i8 = 2;
@@ -129,10 +117,7 @@ async fn main(spawner: Spawner) {
129 }) 117 })
130 .await 118 .await
131 .unwrap(); 119 .unwrap();
132 { 120 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
133 let evt = mbox.mac_subsystem.read().await;
134 defmt::info!("{:#x}", evt.mac_event());
135 }
136 121
137 info!("starting FFD device"); 122 info!("starting FFD device");
138 mbox.mac_subsystem 123 mbox.mac_subsystem
@@ -147,10 +132,7 @@ async fn main(spawner: Spawner) {
147 }) 132 })
148 .await 133 .await
149 .unwrap(); 134 .unwrap();
150 { 135 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
151 let evt = mbox.mac_subsystem.read().await;
152 defmt::info!("{:#x}", evt.mac_event());
153 }
154 136
155 info!("setting RX on when idle"); 137 info!("setting RX on when idle");
156 let rx_on_while_idle: bool = true; 138 let rx_on_while_idle: bool = true;
@@ -161,14 +143,11 @@ async fn main(spawner: Spawner) {
161 }) 143 })
162 .await 144 .await
163 .unwrap(); 145 .unwrap();
164 { 146 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
165 let evt = mbox.mac_subsystem.read().await;
166 defmt::info!("{:#x}", evt.mac_event());
167 }
168 147
169 loop { 148 loop {
170 let evt = mbox.mac_subsystem.read().await; 149 let evt = mbox.mac_subsystem.read().await;
171 if let Ok(evt) = evt.mac_event() { 150 if let Ok(evt) = evt {
172 defmt::info!("parsed mac event"); 151 defmt::info!("parsed mac event");
173 defmt::info!("{:#x}", evt); 152 defmt::info!("{:#x}", evt);
174 153
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 000000000..bbcd0a70f
--- /dev/null
+++ b/examples/stm32wb/src/bin/mac_ffd_net.rs
@@ -0,0 +1,170 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::bind_interrupts;
8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
9use embassy_stm32_wpan::mac::commands::{ResetRequest, SetRequest, StartRequest};
10use embassy_stm32_wpan::mac::typedefs::{MacChannel, PanId, PibId};
11use embassy_stm32_wpan::mac::{self, Runner};
12use embassy_stm32_wpan::sub::mm;
13use embassy_stm32_wpan::TlMbox;
14use static_cell::make_static;
15use {defmt_rtt as _, panic_probe as _};
16
17bind_interrupts!(struct Irqs{
18 IPCC_C1_RX => ReceiveInterruptHandler;
19 IPCC_C1_TX => TransmitInterruptHandler;
20});
21
22#[embassy_executor::task]
23async fn run_mm_queue(memory_manager: mm::MemoryManager) {
24 memory_manager.run_queue().await;
25}
26
27#[embassy_executor::task]
28async fn run_mac(runner: &'static Runner<'static>) {
29 runner.run().await;
30}
31
32#[embassy_executor::main]
33async fn main(spawner: Spawner) {
34 /*
35 How to make this work:
36
37 - Obtain a NUCLEO-STM32WB55 from your preferred supplier.
38 - Download and Install STM32CubeProgrammer.
39 - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from
40 gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x
41 - Open STM32CubeProgrammer
42 - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware.
43 - Once complete, click connect to connect to the device.
44 - On the left hand pane, click the RSS signal icon to open "Firmware Upgrade Services".
45 - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file
46 - Select that file, the memory address, "verify download", and then "Firmware Upgrade".
47 - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the
48 stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address.
49 - Select that file, the memory address, "verify download", and then "Firmware Upgrade".
50 - Select "Start Wireless Stack".
51 - Disconnect from the device.
52 - In the examples folder for stm32wb, modify the memory.x file to match your target device.
53 - Run this example.
54
55 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name.
56 */
57
58 let p = embassy_stm32::init(Default::default());
59 info!("Hello World!");
60
61 let config = Config::default();
62 let mbox = TlMbox::init(p.IPCC, Irqs, config);
63
64 spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap();
65
66 let sys_event = mbox.sys_subsystem.read().await;
67 info!("sys event: {}", sys_event.payload());
68
69 core::mem::drop(sys_event);
70
71 let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await;
72 info!("initialized mac: {}", result);
73
74 info!("resetting");
75 mbox.mac_subsystem
76 .send_command(&ResetRequest {
77 set_default_pib: true,
78 ..Default::default()
79 })
80 .await
81 .unwrap();
82 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
83
84 info!("setting extended address");
85 let extended_address: u64 = 0xACDE480000000001;
86 mbox.mac_subsystem
87 .send_command(&SetRequest {
88 pib_attribute_ptr: &extended_address as *const _ as *const u8,
89 pib_attribute: PibId::ExtendedAddress,
90 })
91 .await
92 .unwrap();
93 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
94
95 info!("setting short address");
96 let short_address: u16 = 0x1122;
97 mbox.mac_subsystem
98 .send_command(&SetRequest {
99 pib_attribute_ptr: &short_address as *const _ as *const u8,
100 pib_attribute: PibId::ShortAddress,
101 })
102 .await
103 .unwrap();
104 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
105
106 info!("setting association permit");
107 let association_permit: bool = true;
108 mbox.mac_subsystem
109 .send_command(&SetRequest {
110 pib_attribute_ptr: &association_permit as *const _ as *const u8,
111 pib_attribute: PibId::AssociationPermit,
112 })
113 .await
114 .unwrap();
115 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
116
117 info!("setting TX power");
118 let transmit_power: i8 = 2;
119 mbox.mac_subsystem
120 .send_command(&SetRequest {
121 pib_attribute_ptr: &transmit_power as *const _ as *const u8,
122 pib_attribute: PibId::TransmitPower,
123 })
124 .await
125 .unwrap();
126 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
127
128 info!("starting FFD device");
129 mbox.mac_subsystem
130 .send_command(&StartRequest {
131 pan_id: PanId([0x1A, 0xAA]),
132 channel_number: MacChannel::Channel16,
133 beacon_order: 0x0F,
134 superframe_order: 0x0F,
135 pan_coordinator: true,
136 battery_life_extension: false,
137 ..Default::default()
138 })
139 .await
140 .unwrap();
141 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
142
143 info!("setting RX on when idle");
144 let rx_on_while_idle: bool = true;
145 mbox.mac_subsystem
146 .send_command(&SetRequest {
147 pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8,
148 pib_attribute: PibId::RxOnWhenIdle,
149 })
150 .await
151 .unwrap();
152 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
153
154 let tx_queue = [
155 make_static!([0u8; 127]),
156 make_static!([0u8; 127]),
157 make_static!([0u8; 127]),
158 make_static!([0u8; 127]),
159 make_static!([0u8; 127]),
160 ];
161
162 let runner = make_static!(Runner::new(mbox.mac_subsystem, tx_queue));
163
164 spawner.spawn(run_mac(runner)).unwrap();
165
166 let (driver, control) = mac::new(runner).await;
167
168 let _ = driver;
169 let _ = control;
170}
diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs
index 7cb401d89..4d8b6601a 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) {
75 }) 75 })
76 .await 76 .await
77 .unwrap(); 77 .unwrap();
78 { 78 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
79 let evt = mbox.mac_subsystem.read().await;
80 defmt::info!("{:#x}", evt.mac_event());
81 }
82 79
83 info!("setting extended address"); 80 info!("setting extended address");
84 let extended_address: u64 = 0xACDE480000000002; 81 let extended_address: u64 = 0xACDE480000000002;
@@ -89,10 +86,7 @@ async fn main(spawner: Spawner) {
89 }) 86 })
90 .await 87 .await
91 .unwrap(); 88 .unwrap();
92 { 89 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
93 let evt = mbox.mac_subsystem.read().await;
94 defmt::info!("{:#x}", evt.mac_event());
95 }
96 90
97 info!("getting extended address"); 91 info!("getting extended address");
98 mbox.mac_subsystem 92 mbox.mac_subsystem
@@ -104,10 +98,10 @@ async fn main(spawner: Spawner) {
104 .unwrap(); 98 .unwrap();
105 99
106 { 100 {
107 let evt = mbox.mac_subsystem.read().await; 101 let evt = mbox.mac_subsystem.read().await.unwrap();
108 info!("{:#x}", evt.mac_event()); 102 info!("{:#x}", evt);
109 103
110 if let Ok(MacEvent::MlmeGetCnf(evt)) = evt.mac_event() { 104 if let MacEvent::MlmeGetCnf(evt) = evt {
111 if evt.pib_attribute_value_len == 8 { 105 if evt.pib_attribute_value_len == 8 {
112 let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; 106 let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) };
113 107
@@ -132,10 +126,10 @@ async fn main(spawner: Spawner) {
132 info!("{}", a); 126 info!("{}", a);
133 mbox.mac_subsystem.send_command(&a).await.unwrap(); 127 mbox.mac_subsystem.send_command(&a).await.unwrap();
134 let short_addr = { 128 let short_addr = {
135 let evt = mbox.mac_subsystem.read().await; 129 let evt = mbox.mac_subsystem.read().await.unwrap();
136 info!("{:#x}", evt.mac_event()); 130 info!("{:#x}", evt);
137 131
138 if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt.mac_event() { 132 if let MacEvent::MlmeAssociateCnf(conf) = evt {
139 conf.assoc_short_address 133 conf.assoc_short_address
140 } else { 134 } else {
141 defmt::panic!() 135 defmt::panic!()
@@ -151,8 +145,8 @@ async fn main(spawner: Spawner) {
151 .await 145 .await
152 .unwrap(); 146 .unwrap();
153 { 147 {
154 let evt = mbox.mac_subsystem.read().await; 148 let evt = mbox.mac_subsystem.read().await.unwrap();
155 info!("{:#x}", evt.mac_event()); 149 info!("{:#x}", evt);
156 } 150 }
157 151
158 info!("sending data"); 152 info!("sending data");
@@ -175,12 +169,14 @@ async fn main(spawner: Spawner) {
175 .await 169 .await
176 .unwrap(); 170 .unwrap();
177 { 171 {
178 let evt = mbox.mac_subsystem.read().await; 172 let evt = mbox.mac_subsystem.read().await.unwrap();
179 info!("{:#x}", evt.mac_event()); 173 info!("{:#x}", evt);
180 } 174 }
181 175
182 loop { 176 loop {
183 let evt = mbox.mac_subsystem.read().await; 177 match mbox.mac_subsystem.read().await {
184 info!("{:#x}", evt.mac_event()); 178 Ok(evt) => info!("{:#x}", evt),
179 _ => continue,
180 };
185 } 181 }
186} 182}
diff --git a/tests/stm32/src/bin/wpan_mac.rs b/tests/stm32/src/bin/wpan_mac.rs
index d64a5ef81..b04a19ee9 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) {
56 .await 56 .await
57 .unwrap(); 57 .unwrap();
58 { 58 {
59 let evt = mbox.mac_subsystem.read().await; 59 let evt = mbox.mac_subsystem.read().await.unwrap();
60 info!("{:#x}", evt.mac_event()); 60 info!("{:#x}", evt);
61 } 61 }
62 62
63 info!("setting extended address"); 63 info!("setting extended address");
@@ -70,8 +70,8 @@ async fn main(spawner: Spawner) {
70 .await 70 .await
71 .unwrap(); 71 .unwrap();
72 { 72 {
73 let evt = mbox.mac_subsystem.read().await; 73 let evt = mbox.mac_subsystem.read().await.unwrap();
74 info!("{:#x}", evt.mac_event()); 74 info!("{:#x}", evt);
75 } 75 }
76 76
77 info!("getting extended address"); 77 info!("getting extended address");
@@ -82,11 +82,12 @@ async fn main(spawner: Spawner) {
82 }) 82 })
83 .await 83 .await
84 .unwrap(); 84 .unwrap();
85
85 { 86 {
86 let evt = mbox.mac_subsystem.read().await; 87 let evt = mbox.mac_subsystem.read().await.unwrap();
87 info!("{:#x}", evt.mac_event()); 88 info!("{:#x}", evt);
88 89
89 if let Ok(MacEvent::MlmeGetCnf(evt)) = evt.mac_event() { 90 if let MacEvent::MlmeGetCnf(evt) = evt {
90 if evt.pib_attribute_value_len == 8 { 91 if evt.pib_attribute_value_len == 8 {
91 let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; 92 let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) };
92 93
@@ -110,10 +111,13 @@ async fn main(spawner: Spawner) {
110 }; 111 };
111 info!("{}", a); 112 info!("{}", a);
112 mbox.mac_subsystem.send_command(&a).await.unwrap(); 113 mbox.mac_subsystem.send_command(&a).await.unwrap();
113 { 114 let short_addr = if let MacEvent::MlmeAssociateCnf(conf) = mbox.mac_subsystem.read().await.unwrap() {
114 let evt = mbox.mac_subsystem.read().await; 115 conf.assoc_short_address
115 info!("{:#x}", evt.mac_event()); 116 } else {
116 } 117 defmt::panic!()
118 };
119
120 info!("{}", short_addr);
117 121
118 info!("Test OK"); 122 info!("Test OK");
119 cortex_m::asm::bkpt(); 123 cortex_m::asm::bkpt();