aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32-wpan/CHANGELOG.md1
-rw-r--r--embassy-stm32-wpan/Cargo.toml1
-rw-r--r--embassy-stm32-wpan/src/mac/control.rs169
-rw-r--r--embassy-stm32-wpan/src/mac/driver.rs120
-rw-r--r--embassy-stm32-wpan/src/mac/mod.rs6
-rw-r--r--embassy-stm32-wpan/src/mac/runner.rs73
-rw-r--r--embassy-stm32-wpan/src/sub/mac.rs83
-rw-r--r--examples/stm32wb/src/bin/mac_ffd_net.rs115
8 files changed, 368 insertions, 200 deletions
diff --git a/embassy-stm32-wpan/CHANGELOG.md b/embassy-stm32-wpan/CHANGELOG.md
index 7042ad14c..c567fe1de 100644
--- a/embassy-stm32-wpan/CHANGELOG.md
+++ b/embassy-stm32-wpan/CHANGELOG.md
@@ -8,4 +8,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8<!-- next-header --> 8<!-- next-header -->
9## Unreleased - ReleaseDate 9## Unreleased - ReleaseDate
10 10
11- restructure to allow embassy net driver to work.
11- First release with changelog. 12- First release with changelog.
diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml
index 0802b7328..75d978d1a 100644
--- a/embassy-stm32-wpan/Cargo.toml
+++ b/embassy-stm32-wpan/Cargo.toml
@@ -40,6 +40,7 @@ log = { version = "0.4.17", optional = true }
40cortex-m = "0.7.6" 40cortex-m = "0.7.6"
41heapless = "0.8" 41heapless = "0.8"
42aligned = "0.4.1" 42aligned = "0.4.1"
43critical-section = "1.1"
43 44
44bit_field = "0.10.2" 45bit_field = "0.10.2"
45stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } 46stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] }
diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs
index e8d2f9f7b..8fb971da3 100644
--- a/embassy-stm32-wpan/src/mac/control.rs
+++ b/embassy-stm32-wpan/src/mac/control.rs
@@ -1,65 +1,184 @@
1use core::cell::RefCell;
1use core::future::Future; 2use core::future::Future;
3use core::sync::atomic::{Ordering, compiler_fence};
2use core::task; 4use core::task;
3use core::task::Poll; 5use core::task::Poll;
4 6
7use embassy_net_driver::LinkState;
8use embassy_sync::blocking_mutex;
5use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 9use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
6use embassy_sync::mutex::MutexGuard; 10use embassy_sync::mutex::Mutex;
7use embassy_sync::signal::Signal; 11use embassy_sync::signal::Signal;
8use futures_util::FutureExt; 12use futures_util::FutureExt;
9 13
10use super::commands::MacCommand; 14use crate::mac::commands::*;
11use super::event::MacEvent; 15use crate::mac::driver::NetworkState;
12use super::typedefs::MacError; 16use crate::mac::event::MacEvent;
13use crate::mac::runner::Runner; 17use crate::mac::runner::ZeroCopyPubSub;
18use crate::mac::typedefs::*;
19use crate::sub::mac::MacTx;
14 20
15pub struct Control<'a> { 21pub struct Control<'a> {
16 runner: &'a Runner<'a>, 22 rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>,
23 mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx>,
24 #[allow(unused)]
25 network_state: &'a blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>,
17} 26}
18 27
19impl<'a> Control<'a> { 28impl<'a> Control<'a> {
20 pub(crate) fn new(runner: &'a Runner<'a>) -> Self { 29 pub(crate) fn new(
21 Self { runner: runner } 30 rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>,
31 mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx>,
32 network_state: &'a blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>,
33 ) -> Self {
34 Self {
35 rx_event_channel,
36 mac_tx,
37 network_state,
38 }
39 }
40
41 pub async fn init_link(&mut self, short_address: [u8; 2], extended_address: [u8; 8], pan_id: [u8; 2]) {
42 debug!("resetting");
43
44 debug!(
45 "{:#x}",
46 self.send_command_and_get_response(&ResetRequest {
47 set_default_pib: true,
48 ..Default::default()
49 })
50 .await
51 .unwrap()
52 .await
53 );
54
55 debug!("setting extended address");
56 let extended_address: u64 = u64::from_be_bytes(extended_address);
57 debug!(
58 "{:#x}",
59 self.send_command_and_get_response(&SetRequest {
60 pib_attribute_ptr: &extended_address as *const _ as *const u8,
61 pib_attribute: PibId::ExtendedAddress,
62 })
63 .await
64 .unwrap()
65 .await
66 );
67
68 debug!("setting short address");
69 let short_address: u16 = u16::from_be_bytes(short_address);
70 debug!(
71 "{:#x}",
72 self.send_command_and_get_response(&SetRequest {
73 pib_attribute_ptr: &short_address as *const _ as *const u8,
74 pib_attribute: PibId::ShortAddress,
75 })
76 .await
77 .unwrap()
78 .await
79 );
80
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");
86 let association_permit: bool = true;
87 debug!(
88 "{:#x}",
89 self.send_command_and_get_response(&SetRequest {
90 pib_attribute_ptr: &association_permit as *const _ as *const u8,
91 pib_attribute: PibId::AssociationPermit,
92 })
93 .await
94 .unwrap()
95 .await
96 );
97
98 debug!("setting TX power");
99 let transmit_power: i8 = 2;
100 debug!(
101 "{:#x}",
102 self.send_command_and_get_response(&SetRequest {
103 pib_attribute_ptr: &transmit_power as *const _ as *const u8,
104 pib_attribute: PibId::TransmitPower,
105 })
106 .await
107 .unwrap()
108 .await
109 );
110
111 debug!("starting FFD device");
112 debug!(
113 "{:#x}",
114 self.send_command_and_get_response(&StartRequest {
115 pan_id: PanId(pan_id),
116 channel_number: MacChannel::Channel16,
117 beacon_order: 0x0F,
118 superframe_order: 0x0F,
119 pan_coordinator: true,
120 battery_life_extension: false,
121 ..Default::default()
122 })
123 .await
124 .unwrap()
125 .await
126 );
127
128 debug!("setting RX on when idle");
129 let rx_on_while_idle: bool = true;
130 debug!(
131 "{:#x}",
132 self.send_command_and_get_response(&SetRequest {
133 pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8,
134 pib_attribute: PibId::RxOnWhenIdle,
135 })
136 .await
137 .unwrap()
138 .await
139 );
140
141 critical_section::with(|cs| {
142 let mut network_state = self.network_state.borrow(cs).borrow_mut();
143
144 network_state.link_state = LinkState::Up;
145 network_state.link_waker.wake();
146 });
22 } 147 }
23 148
24 pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError> 149 pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError>
25 where 150 where
26 T: MacCommand, 151 T: MacCommand,
27 { 152 {
28 let _wm = self.runner.write_mutex.lock().await; 153 self.mac_tx.lock().await.send_command(cmd).await
29
30 self.runner.mac_subsystem.send_command(cmd).await
31 } 154 }
32 155
33 pub async fn send_command_and_get_response<T>(&self, cmd: &T) -> Result<EventToken<'a>, MacError> 156 pub async fn send_command_and_get_response<T>(&self, cmd: &T) -> Result<EventToken<'a>, MacError>
34 where 157 where
35 T: MacCommand, 158 T: MacCommand,
36 { 159 {
37 let rm = self.runner.read_mutex.lock().await; 160 let token = EventToken::new(self.rx_event_channel);
38 let _wm = self.runner.write_mutex.lock().await; 161
39 let token = EventToken::new(self.runner, rm); 162 compiler_fence(Ordering::Release);
40 163
41 self.runner.mac_subsystem.send_command(cmd).await?; 164 self.mac_tx.lock().await.send_command(cmd).await?;
42 165
43 Ok(token) 166 Ok(token)
44 } 167 }
45} 168}
46 169
47pub struct EventToken<'a> { 170pub struct EventToken<'a> {
48 runner: &'a Runner<'a>, 171 rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>,
49 _mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>,
50} 172}
51 173
52impl<'a> EventToken<'a> { 174impl<'a> EventToken<'a> {
53 pub(crate) fn new(runner: &'a Runner<'a>, mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>) -> Self { 175 pub(crate) fn new(rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>) -> Self {
54 // Enable event receiving 176 // Enable event receiving
55 runner.rx_event_channel.lock(|s| { 177 rx_event_channel.lock(|s| {
56 *s.borrow_mut() = Some(Signal::new()); 178 *s.borrow_mut() = Some(Signal::new());
57 }); 179 });
58 180
59 Self { 181 Self { rx_event_channel }
60 runner: runner,
61 _mutex_guard: mutex_guard,
62 }
63 } 182 }
64} 183}
65 184
@@ -67,7 +186,7 @@ impl<'a> Future for EventToken<'a> {
67 type Output = MacEvent<'a>; 186 type Output = MacEvent<'a>;
68 187
69 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { 188 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| { 189 self.rx_event_channel.lock(|s| {
71 let signal = s.borrow_mut(); 190 let signal = s.borrow_mut();
72 let signal = match &*signal { 191 let signal = match &*signal {
73 Some(s) => s, 192 Some(s) => s,
@@ -88,7 +207,7 @@ impl<'a> Drop for EventToken<'a> {
88 fn drop(&mut self) { 207 fn drop(&mut self) {
89 // Disable event receiving 208 // Disable event receiving
90 // This will also drop the contained event, if it exists, and will free up receiving the next event 209 // 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| { 210 self.rx_event_channel.lock(|s| {
92 *s.borrow_mut() = None; 211 *s.borrow_mut() = None;
93 }); 212 });
94 } 213 }
diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs
index 480ac3790..819299b48 100644
--- a/embassy-stm32-wpan/src/mac/driver.rs
+++ b/embassy-stm32-wpan/src/mac/driver.rs
@@ -1,22 +1,97 @@
1#![deny(unused_must_use)] 1#![deny(unused_must_use)]
2 2
3use core::cell::RefCell;
3use core::task::Context; 4use core::task::Context;
4 5
5use embassy_net_driver::{Capabilities, HardwareAddress, LinkState}; 6use embassy_net_driver::{Capabilities, HardwareAddress, LinkState};
7use embassy_sync::blocking_mutex;
6use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 8use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
7use embassy_sync::channel::Channel; 9use embassy_sync::channel::Channel;
10use embassy_sync::mutex::Mutex;
11use embassy_sync::waitqueue::AtomicWaker;
8 12
9use crate::mac::MTU;
10use crate::mac::event::MacEvent; 13use crate::mac::event::MacEvent;
11use crate::mac::runner::Runner; 14use crate::mac::runner::{BUF_SIZE, ZeroCopyPubSub};
15use crate::mac::{Control, MTU, Runner};
16use crate::sub::mac::{Mac, MacRx, MacTx};
17
18pub struct NetworkState {
19 pub mac_addr: [u8; 8],
20 pub link_state: LinkState,
21 pub link_waker: AtomicWaker,
22}
23
24impl NetworkState {
25 pub const fn new() -> Self {
26 Self {
27 mac_addr: [0u8; 8],
28 link_state: LinkState::Down,
29 link_waker: AtomicWaker::new(),
30 }
31 }
32}
33
34pub struct DriverState<'d> {
35 pub mac_tx: Mutex<CriticalSectionRawMutex, MacTx>,
36 pub mac_rx: MacRx,
37 pub rx_event_channel: ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'d>>,
38 pub rx_data_channel: Channel<CriticalSectionRawMutex, MacEvent<'d>, 1>,
39 pub tx_data_channel: Channel<CriticalSectionRawMutex, (&'d mut [u8; MTU], usize), BUF_SIZE>,
40 pub tx_buf_channel: Channel<CriticalSectionRawMutex, &'d mut [u8; MTU], BUF_SIZE>,
41 pub tx_buf_queue: [[u8; MTU]; BUF_SIZE],
42 pub network_state: blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>,
43}
44
45impl<'d> DriverState<'d> {
46 pub const fn new(mac: Mac) -> Self {
47 let (mac_rx, mac_tx) = mac.split();
48 let mac_tx = Mutex::new(mac_tx);
49
50 Self {
51 mac_tx,
52 mac_rx,
53 rx_event_channel: ZeroCopyPubSub::new(RefCell::new(None)),
54 rx_data_channel: Channel::new(),
55 tx_data_channel: Channel::new(),
56 tx_buf_channel: Channel::new(),
57 tx_buf_queue: [[0u8; MTU]; BUF_SIZE],
58 network_state: blocking_mutex::Mutex::new(RefCell::new(NetworkState::new())),
59 }
60 }
61}
12 62
13pub struct Driver<'d> { 63pub struct Driver<'d> {
14 runner: &'d Runner<'d>, 64 tx_data_channel: &'d Channel<CriticalSectionRawMutex, (&'d mut [u8; MTU], usize), BUF_SIZE>,
65 tx_buf_channel: &'d Channel<CriticalSectionRawMutex, &'d mut [u8; MTU], BUF_SIZE>,
66 rx_data_channel: &'d Channel<CriticalSectionRawMutex, MacEvent<'d>, 1>,
67 network_state: &'d blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>,
15} 68}
16 69
17impl<'d> Driver<'d> { 70impl<'d> Driver<'d> {
18 pub(crate) fn new(runner: &'d Runner<'d>) -> Self { 71 pub fn new(driver_state: &'d mut DriverState<'d>) -> (Self, Runner<'d>, Control<'d>) {
19 Self { runner: runner } 72 (
73 Self {
74 tx_data_channel: &driver_state.tx_data_channel,
75 tx_buf_channel: &driver_state.tx_buf_channel,
76 rx_data_channel: &driver_state.rx_data_channel,
77 network_state: &driver_state.network_state,
78 },
79 Runner::new(
80 &driver_state.rx_event_channel,
81 &driver_state.rx_data_channel,
82 &mut driver_state.mac_rx,
83 &driver_state.tx_data_channel,
84 &driver_state.tx_buf_channel,
85 &driver_state.mac_tx,
86 &mut driver_state.tx_buf_queue,
87 &driver_state.network_state,
88 ),
89 Control::new(
90 &driver_state.rx_event_channel,
91 &driver_state.mac_tx,
92 &driver_state.network_state,
93 ),
94 )
20 } 95 }
21} 96}
22 97
@@ -33,16 +108,16 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> {
33 Self: 'a; 108 Self: 'a;
34 109
35 fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { 110 fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
36 if self.runner.rx_channel.poll_ready_to_receive(cx).is_ready() 111 if self.rx_data_channel.poll_ready_to_receive(cx).is_ready()
37 && self.runner.tx_buf_channel.poll_ready_to_receive(cx).is_ready() 112 && self.tx_buf_channel.poll_ready_to_receive(cx).is_ready()
38 { 113 {
39 Some(( 114 Some((
40 RxToken { 115 RxToken {
41 rx: &self.runner.rx_channel, 116 rx: self.rx_data_channel,
42 }, 117 },
43 TxToken { 118 TxToken {
44 tx: &self.runner.tx_channel, 119 tx: self.tx_data_channel,
45 tx_buf: &self.runner.tx_buf_channel, 120 tx_buf: self.tx_buf_channel,
46 }, 121 },
47 )) 122 ))
48 } else { 123 } else {
@@ -51,10 +126,10 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> {
51 } 126 }
52 127
53 fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> { 128 fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> {
54 if self.runner.tx_buf_channel.poll_ready_to_receive(cx).is_ready() { 129 if self.tx_buf_channel.poll_ready_to_receive(cx).is_ready() {
55 Some(TxToken { 130 Some(TxToken {
56 tx: &self.runner.tx_channel, 131 tx: self.tx_data_channel,
57 tx_buf: &self.runner.tx_buf_channel, 132 tx_buf: self.tx_buf_channel,
58 }) 133 })
59 } else { 134 } else {
60 None 135 None
@@ -68,13 +143,20 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> {
68 caps 143 caps
69 } 144 }
70 145
71 fn link_state(&mut self, _cx: &mut Context) -> LinkState { 146 fn link_state(&mut self, cx: &mut Context) -> LinkState {
72 LinkState::Down 147 critical_section::with(|cs| {
148 let network_state = self.network_state.borrow(cs).borrow_mut();
149
150 // Unconditionally register the waker to avoid a race
151 network_state.link_waker.register(cx.waker());
152 network_state.link_state
153 })
73 } 154 }
74 155
75 fn hardware_address(&self) -> HardwareAddress { 156 fn hardware_address(&self) -> HardwareAddress {
76 // self.mac_addr 157 HardwareAddress::Ieee802154(critical_section::with(|cs| {
77 HardwareAddress::Ieee802154([0; 8]) 158 self.network_state.borrow(cs).borrow().mac_addr
159 }))
78 } 160 }
79} 161}
80 162
@@ -99,8 +181,8 @@ impl<'d> embassy_net_driver::RxToken for RxToken<'d> {
99} 181}
100 182
101pub struct TxToken<'d> { 183pub struct TxToken<'d> {
102 tx: &'d Channel<CriticalSectionRawMutex, (&'d mut [u8; MTU], usize), 5>, 184 tx: &'d Channel<CriticalSectionRawMutex, (&'d mut [u8; MTU], usize), BUF_SIZE>,
103 tx_buf: &'d Channel<CriticalSectionRawMutex, &'d mut [u8; MTU], 5>, 185 tx_buf: &'d Channel<CriticalSectionRawMutex, &'d mut [u8; MTU], BUF_SIZE>,
104} 186}
105 187
106impl<'d> embassy_net_driver::TxToken for TxToken<'d> { 188impl<'d> embassy_net_driver::TxToken for TxToken<'d> {
diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs
index c847a5cca..ac50a6b29 100644
--- a/embassy-stm32-wpan/src/mac/mod.rs
+++ b/embassy-stm32-wpan/src/mac/mod.rs
@@ -11,11 +11,7 @@ pub mod runner;
11pub mod typedefs; 11pub mod typedefs;
12 12
13pub use crate::mac::control::Control; 13pub use crate::mac::control::Control;
14use crate::mac::driver::Driver; 14pub use crate::mac::driver::{Driver, DriverState};
15pub use crate::mac::runner::Runner; 15pub use crate::mac::runner::Runner;
16 16
17const MTU: usize = 127; 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/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs
index 2409f994d..26fdf23e0 100644
--- a/embassy-stm32-wpan/src/mac/runner.rs
+++ b/embassy-stm32-wpan/src/mac/runner.rs
@@ -8,52 +8,65 @@ use embassy_sync::mutex::Mutex;
8use embassy_sync::signal::Signal; 8use embassy_sync::signal::Signal;
9 9
10use crate::mac::MTU; 10use crate::mac::MTU;
11use crate::mac::commands::DataRequest; 11use crate::mac::commands::*;
12use crate::mac::driver::NetworkState;
12use crate::mac::event::MacEvent; 13use crate::mac::event::MacEvent;
13use crate::mac::typedefs::{AddressMode, MacAddress, PanId, SecurityLevel}; 14use crate::mac::typedefs::*;
14use crate::sub::mac::Mac; 15use crate::sub::mac::{MacRx, MacTx};
15 16
16type ZeroCopyPubSub<M, T> = blocking_mutex::Mutex<M, RefCell<Option<Signal<NoopRawMutex, T>>>>; 17pub type ZeroCopyPubSub<M, T> = blocking_mutex::Mutex<M, RefCell<Option<Signal<NoopRawMutex, T>>>>;
18
19pub const BUF_SIZE: usize = 3;
17 20
18pub struct Runner<'a> { 21pub struct Runner<'a> {
19 pub(crate) mac_subsystem: Mac,
20 // rx event backpressure is already provided through the MacEvent drop mechanism 22 // rx event backpressure is already provided through the MacEvent drop mechanism
21 // therefore, we don't need to worry about overwriting events 23 // therefore, we don't need to worry about overwriting events
22 pub(crate) rx_event_channel: ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>, 24 rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>,
23 pub(crate) read_mutex: Mutex<CriticalSectionRawMutex, ()>, 25 rx_data_channel: &'a Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>,
24 pub(crate) write_mutex: Mutex<CriticalSectionRawMutex, ()>, 26 mac_rx: &'a mut MacRx,
25 pub(crate) rx_channel: Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>, 27
26 pub(crate) tx_channel: Channel<CriticalSectionRawMutex, (&'a mut [u8; MTU], usize), 5>, 28 tx_data_channel: &'a Channel<CriticalSectionRawMutex, (&'a mut [u8; MTU], usize), BUF_SIZE>,
27 pub(crate) tx_buf_channel: Channel<CriticalSectionRawMutex, &'a mut [u8; MTU], 5>, 29 tx_buf_channel: &'a Channel<CriticalSectionRawMutex, &'a mut [u8; MTU], BUF_SIZE>,
30 mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx>,
31
32 #[allow(unused)]
33 network_state: &'a blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>,
28} 34}
29 35
30impl<'a> Runner<'a> { 36impl<'a> Runner<'a> {
31 pub fn new(mac: Mac, tx_buf_queue: [&'a mut [u8; MTU]; 5]) -> Self { 37 pub fn new(
32 let this = Self { 38 rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>,
33 mac_subsystem: mac, 39 rx_data_channel: &'a Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>,
34 rx_event_channel: blocking_mutex::Mutex::new(RefCell::new(None)), 40 mac_rx: &'a mut MacRx,
35 read_mutex: Mutex::new(()), 41 tx_data_channel: &'a Channel<CriticalSectionRawMutex, (&'a mut [u8; MTU], usize), BUF_SIZE>,
36 write_mutex: Mutex::new(()), 42 tx_buf_channel: &'a Channel<CriticalSectionRawMutex, &'a mut [u8; MTU], BUF_SIZE>,
37 rx_channel: Channel::new(), 43 mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx>,
38 tx_channel: Channel::new(), 44 tx_buf_queue: &'a mut [[u8; MTU]; BUF_SIZE],
39 tx_buf_channel: Channel::new(), 45 network_state: &'a blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>,
40 }; 46 ) -> Self {
41
42 for buf in tx_buf_queue { 47 for buf in tx_buf_queue {
43 this.tx_buf_channel.try_send(buf).unwrap(); 48 tx_buf_channel.try_send(buf).unwrap();
44 } 49 }
45 50
46 this 51 Self {
52 rx_event_channel,
53 rx_data_channel,
54 mac_rx,
55 tx_data_channel,
56 tx_buf_channel,
57 mac_tx,
58 network_state,
59 }
47 } 60 }
48 61
49 pub async fn run(&'a self) -> ! { 62 pub async fn run(&'a self) -> ! {
50 join::join( 63 join::join(
51 async { 64 async {
52 loop { 65 loop {
53 if let Ok(mac_event) = self.mac_subsystem.read().await { 66 if let Ok(mac_event) = self.mac_rx.read().await {
54 match mac_event { 67 match mac_event {
55 MacEvent::McpsDataInd(_) => { 68 MacEvent::McpsDataInd(_) => {
56 self.rx_channel.send(mac_event).await; 69 self.rx_data_channel.send(mac_event).await;
57 } 70 }
58 _ => { 71 _ => {
59 self.rx_event_channel.lock(|s| { 72 self.rx_event_channel.lock(|s| {
@@ -73,11 +86,13 @@ impl<'a> Runner<'a> {
73 let mut msdu_handle = 0x02; 86 let mut msdu_handle = 0x02;
74 87
75 loop { 88 loop {
76 let (buf, len) = self.tx_channel.receive().await; 89 let (buf, len) = self.tx_data_channel.receive().await;
77 let _wm = self.write_mutex.lock().await; 90 let mac_tx = self.mac_tx.lock().await;
91
92 // TODO: skip this if the link state is down
78 93
79 // The mutex should be dropped on the next loop iteration 94 // The mutex should be dropped on the next loop iteration
80 self.mac_subsystem 95 mac_tx
81 .send_command( 96 .send_command(
82 DataRequest { 97 DataRequest {
83 src_addr_mode: AddressMode::Short, 98 src_addr_mode: AddressMode::Short,
diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs
index baf4da979..93cafbc72 100644
--- a/embassy-stm32-wpan/src/sub/mac.rs
+++ b/embassy-stm32-wpan/src/sub/mac.rs
@@ -28,32 +28,39 @@ impl Mac {
28 Self { _private: () } 28 Self { _private: () }
29 } 29 }
30 30
31 /// `HW_IPCC_MAC_802_15_4_EvtNot` 31 pub const fn split(self) -> (MacRx, MacTx) {
32 /// 32 (MacRx { _private: () }, MacTx { _private: () })
33 /// This function will stall if the previous `EvtBox` has not been dropped 33 }
34 pub async fn tl_read(&self) -> EvtBox<Self> {
35 // Wait for the last event box to be dropped
36 poll_fn(|cx| {
37 MAC_WAKER.register(cx.waker());
38 if MAC_EVT_OUT.load(Ordering::SeqCst) {
39 Poll::Pending
40 } else {
41 Poll::Ready(())
42 }
43 })
44 .await;
45 34
46 // Return a new event box 35 pub async fn tl_write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 {
47 Ipcc::receive(channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, || unsafe { 36 MacTx { _private: () }.tl_write_and_get_response(opcode, payload).await
48 // The closure is not async, therefore the closure must execute to completion (cannot be dropped) 37 }
49 // Therefore, the event box is guaranteed to be cleaned up if it's not leaked
50 MAC_EVT_OUT.store(true, Ordering::SeqCst);
51 38
52 Some(EvtBox::new(MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _)) 39 pub async fn tl_write(&self, opcode: u16, payload: &[u8]) {
53 }) 40 MacTx { _private: () }.tl_write(opcode, payload).await
54 .await
55 } 41 }
56 42
43 pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError>
44 where
45 T: MacCommand,
46 {
47 MacTx { _private: () }.send_command(cmd).await
48 }
49
50 pub async fn tl_read(&self) -> EvtBox<Mac> {
51 MacRx { _private: () }.tl_read().await
52 }
53
54 pub async fn read(&self) -> Result<MacEvent<'_>, ()> {
55 MacRx { _private: () }.read().await
56 }
57}
58
59pub struct MacTx {
60 _private: (),
61}
62
63impl MacTx {
57 /// `HW_IPCC_MAC_802_15_4_CmdEvtNot` 64 /// `HW_IPCC_MAC_802_15_4_CmdEvtNot`
58 pub async fn tl_write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { 65 pub async fn tl_write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 {
59 self.tl_write(opcode, payload).await; 66 self.tl_write(opcode, payload).await;
@@ -92,6 +99,38 @@ impl Mac {
92 Err(MacError::from(response)) 99 Err(MacError::from(response))
93 } 100 }
94 } 101 }
102}
103
104pub struct MacRx {
105 _private: (),
106}
107
108impl MacRx {
109 /// `HW_IPCC_MAC_802_15_4_EvtNot`
110 ///
111 /// This function will stall if the previous `EvtBox` has not been dropped
112 pub async fn tl_read(&self) -> EvtBox<Mac> {
113 // Wait for the last event box to be dropped
114 poll_fn(|cx| {
115 MAC_WAKER.register(cx.waker());
116 if MAC_EVT_OUT.load(Ordering::SeqCst) {
117 Poll::Pending
118 } else {
119 Poll::Ready(())
120 }
121 })
122 .await;
123
124 // Return a new event box
125 Ipcc::receive(channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, || unsafe {
126 // The closure is not async, therefore the closure must execute to completion (cannot be dropped)
127 // Therefore, the event box is guaranteed to be cleaned up if it's not leaked
128 MAC_EVT_OUT.store(true, Ordering::SeqCst);
129
130 Some(EvtBox::new(MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _))
131 })
132 .await
133 }
95 134
96 pub async fn read(&self) -> Result<MacEvent<'_>, ()> { 135 pub async fn read(&self) -> Result<MacEvent<'_>, ()> {
97 MacEvent::new(self.tl_read().await) 136 MacEvent::new(self.tl_read().await)
diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs
index 5296943a1..9b705dda9 100644
--- a/examples/stm32wb/src/bin/mac_ffd_net.rs
+++ b/examples/stm32wb/src/bin/mac_ffd_net.rs
@@ -7,9 +7,7 @@ use embassy_stm32::bind_interrupts;
7use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 7use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
8use embassy_stm32::rcc::WPAN_DEFAULT; 8use embassy_stm32::rcc::WPAN_DEFAULT;
9use embassy_stm32_wpan::TlMbox; 9use embassy_stm32_wpan::TlMbox;
10use embassy_stm32_wpan::mac::commands::{ResetRequest, SetRequest, StartRequest}; 10use embassy_stm32_wpan::mac::{Driver, DriverState, Runner};
11use embassy_stm32_wpan::mac::typedefs::{MacChannel, PanId, PibId};
12use embassy_stm32_wpan::mac::{self, Runner};
13use embassy_stm32_wpan::sub::mm; 11use embassy_stm32_wpan::sub::mm;
14use static_cell::StaticCell; 12use static_cell::StaticCell;
15use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
@@ -72,106 +70,23 @@ async fn main(spawner: Spawner) {
72 let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; 70 let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await;
73 info!("initialized mac: {}", result); 71 info!("initialized mac: {}", result);
74 72
75 info!("resetting"); 73 static DRIVER_STATE: StaticCell<DriverState> = StaticCell::new();
76 mbox.mac_subsystem
77 .send_command(&ResetRequest {
78 set_default_pib: true,
79 ..Default::default()
80 })
81 .await
82 .unwrap();
83 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
84
85 info!("setting extended address");
86 let extended_address: u64 = 0xACDE480000000001;
87 mbox.mac_subsystem
88 .send_command(&SetRequest {
89 pib_attribute_ptr: &extended_address as *const _ as *const u8,
90 pib_attribute: PibId::ExtendedAddress,
91 })
92 .await
93 .unwrap();
94 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
95
96 info!("setting short address");
97 let short_address: u16 = 0x1122;
98 mbox.mac_subsystem
99 .send_command(&SetRequest {
100 pib_attribute_ptr: &short_address as *const _ as *const u8,
101 pib_attribute: PibId::ShortAddress,
102 })
103 .await
104 .unwrap();
105 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
106
107 info!("setting association permit");
108 let association_permit: bool = true;
109 mbox.mac_subsystem
110 .send_command(&SetRequest {
111 pib_attribute_ptr: &association_permit as *const _ as *const u8,
112 pib_attribute: PibId::AssociationPermit,
113 })
114 .await
115 .unwrap();
116 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
117
118 info!("setting TX power");
119 let transmit_power: i8 = 2;
120 mbox.mac_subsystem
121 .send_command(&SetRequest {
122 pib_attribute_ptr: &transmit_power as *const _ as *const u8,
123 pib_attribute: PibId::TransmitPower,
124 })
125 .await
126 .unwrap();
127 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
128
129 info!("starting FFD device");
130 mbox.mac_subsystem
131 .send_command(&StartRequest {
132 pan_id: PanId([0x1A, 0xAA]),
133 channel_number: MacChannel::Channel16,
134 beacon_order: 0x0F,
135 superframe_order: 0x0F,
136 pan_coordinator: true,
137 battery_life_extension: false,
138 ..Default::default()
139 })
140 .await
141 .unwrap();
142 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
143
144 info!("setting RX on when idle");
145 let rx_on_while_idle: bool = true;
146 mbox.mac_subsystem
147 .send_command(&SetRequest {
148 pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8,
149 pib_attribute: PibId::RxOnWhenIdle,
150 })
151 .await
152 .unwrap();
153 defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
154
155 static TX1: StaticCell<[u8; 127]> = StaticCell::new();
156 static TX2: StaticCell<[u8; 127]> = StaticCell::new();
157 static TX3: StaticCell<[u8; 127]> = StaticCell::new();
158 static TX4: StaticCell<[u8; 127]> = StaticCell::new();
159 static TX5: StaticCell<[u8; 127]> = StaticCell::new();
160 let tx_queue = [
161 TX1.init([0u8; 127]),
162 TX2.init([0u8; 127]),
163 TX3.init([0u8; 127]),
164 TX4.init([0u8; 127]),
165 TX5.init([0u8; 127]),
166 ];
167
168 static RUNNER: StaticCell<Runner> = StaticCell::new(); 74 static RUNNER: StaticCell<Runner> = StaticCell::new();
169 let runner = RUNNER.init(Runner::new(mbox.mac_subsystem, tx_queue));
170 75
171 spawner.spawn(run_mac(runner).unwrap()); 76 let driver_state = DRIVER_STATE.init(DriverState::new(mbox.mac_subsystem));
77 let (driver, runner, mut control) = Driver::new(driver_state);
78
79 spawner.spawn(run_mac(RUNNER.init(runner)).unwrap());
80
81 control
82 .init_link(
83 0x1122u16.to_be_bytes().try_into().unwrap(),
84 0xACDE480000000001u64.to_be_bytes().try_into().unwrap(),
85 [0x1A, 0xAA],
86 )
87 .await;
172 88
173 let (driver, control) = mac::new(runner).await; 89 cortex_m::asm::bkpt();
174 90
175 let _ = driver; 91 let _ = driver;
176 let _ = control;
177} 92}