aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32-wpan/src/wb55/mac/runner.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32-wpan/src/wb55/mac/runner.rs')
-rw-r--r--embassy-stm32-wpan/src/wb55/mac/runner.rs151
1 files changed, 151 insertions, 0 deletions
diff --git a/embassy-stm32-wpan/src/wb55/mac/runner.rs b/embassy-stm32-wpan/src/wb55/mac/runner.rs
new file mode 100644
index 000000000..3b7d895df
--- /dev/null
+++ b/embassy-stm32-wpan/src/wb55/mac/runner.rs
@@ -0,0 +1,151 @@
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;
9use smoltcp::wire::Ieee802154FrameType;
10use smoltcp::wire::ieee802154::Frame;
11
12use crate::mac::MTU;
13use crate::mac::commands::*;
14use crate::mac::driver::NetworkState;
15use crate::mac::event::MacEvent;
16use crate::sub::mac::{MacRx, MacTx};
17
18pub type ZeroCopyPubSub<M, T> = blocking_mutex::Mutex<M, RefCell<Option<Signal<NoopRawMutex, T>>>>;
19
20pub const BUF_SIZE: usize = 3;
21
22pub struct Runner<'a> {
23 // rx event backpressure is already provided through the MacEvent drop mechanism
24 // therefore, we don't need to worry about overwriting events
25 rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>,
26 rx_data_channel: &'a Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>,
27 mac_rx: Mutex<NoopRawMutex, &'a mut MacRx<'a>>,
28
29 tx_data_channel: &'a Channel<CriticalSectionRawMutex, (&'a mut [u8; MTU], usize), BUF_SIZE>,
30 tx_buf_channel: &'a Channel<CriticalSectionRawMutex, &'a mut [u8; MTU], BUF_SIZE>,
31 mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx<'a>>,
32
33 #[allow(unused)]
34 network_state: &'a blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>,
35}
36
37impl<'a> Runner<'a> {
38 pub(crate) fn new(
39 rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>,
40 rx_data_channel: &'a Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>,
41 mac_rx: &'a mut MacRx<'a>,
42 tx_data_channel: &'a Channel<CriticalSectionRawMutex, (&'a mut [u8; MTU], usize), BUF_SIZE>,
43 tx_buf_channel: &'a Channel<CriticalSectionRawMutex, &'a mut [u8; MTU], BUF_SIZE>,
44 mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx<'a>>,
45 tx_buf_queue: &'a mut [[u8; MTU]; BUF_SIZE],
46 network_state: &'a blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>,
47 short_address: [u8; 2],
48 mac_address: [u8; 8],
49 ) -> Self {
50 for buf in tx_buf_queue {
51 tx_buf_channel.try_send(buf).unwrap();
52 }
53
54 critical_section::with(|cs| {
55 let mut network_state = network_state.borrow(cs).borrow_mut();
56
57 network_state.mac_addr = mac_address;
58 network_state.short_addr = short_address;
59 });
60
61 Self {
62 rx_event_channel,
63 rx_data_channel,
64 mac_rx: Mutex::new(mac_rx),
65 tx_data_channel,
66 tx_buf_channel,
67 mac_tx,
68 network_state,
69 }
70 }
71
72 async fn send_request<T: MacCommand, U: TryInto<T>>(&self, frame: U) -> Result<(), ()>
73 where
74 (): From<<U as TryInto<T>>::Error>,
75 {
76 let request: T = frame.try_into()?;
77 self.mac_tx.lock().await.send_command(&request).await.map_err(|_| ())?;
78
79 Ok(())
80 }
81
82 pub async fn run(&'a self) -> ! {
83 join::join(
84 async {
85 loop {
86 if let Ok(mac_event) = self.mac_rx.try_lock().unwrap().read().await {
87 match mac_event {
88 MacEvent::MlmeAssociateCnf(_)
89 | MacEvent::MlmeDisassociateCnf(_)
90 | MacEvent::MlmeGetCnf(_)
91 | MacEvent::MlmeGtsCnf(_)
92 | MacEvent::MlmeResetCnf(_)
93 | MacEvent::MlmeRxEnableCnf(_)
94 | MacEvent::MlmeScanCnf(_)
95 | MacEvent::MlmeSetCnf(_)
96 | MacEvent::MlmeStartCnf(_)
97 | MacEvent::MlmePollCnf(_)
98 | MacEvent::MlmeDpsCnf(_)
99 | MacEvent::MlmeSoundingCnf(_)
100 | MacEvent::MlmeCalibrateCnf(_)
101 | MacEvent::McpsDataCnf(_)
102 | MacEvent::McpsPurgeCnf(_) => {
103 self.rx_event_channel.lock(|s| {
104 s.borrow().as_ref().map(|signal| signal.signal(mac_event));
105 });
106 }
107 MacEvent::McpsDataInd(_) => {
108 // Pattern should match driver
109 self.rx_data_channel.send(mac_event).await;
110 }
111 _ => {
112 debug!("unhandled mac event: {:#x}", mac_event);
113 }
114 }
115 }
116 }
117 },
118 async {
119 loop {
120 let (buf, _) = self.tx_data_channel.receive().await;
121
122 // Smoltcp has created this frame, so there's no need to reparse it.
123 let frame = Frame::new_unchecked(&buf);
124
125 let result: Result<(), ()> = match frame.frame_type() {
126 Ieee802154FrameType::Beacon => Err(()),
127 Ieee802154FrameType::Data => self.send_request::<DataRequest, _>(frame).await,
128 Ieee802154FrameType::Acknowledgement => Err(()),
129 Ieee802154FrameType::MacCommand => Err(()),
130 Ieee802154FrameType::Multipurpose => Err(()),
131 Ieee802154FrameType::FragmentOrFrak => Err(()),
132 Ieee802154FrameType::Extended => Err(()),
133 _ => Err(()),
134 };
135
136 if result.is_err() {
137 debug!("failed to parse mac frame");
138 } else {
139 trace!("data frame sent!");
140 }
141
142 // The tx channel should always be of equal capacity to the tx_buf channel
143 self.tx_buf_channel.try_send(buf).unwrap();
144 }
145 },
146 )
147 .await;
148
149 loop {}
150 }
151}