aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32-wpan/src/wb55/mac/control.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32-wpan/src/wb55/mac/control.rs')
-rw-r--r--embassy-stm32-wpan/src/wb55/mac/control.rs204
1 files changed, 204 insertions, 0 deletions
diff --git a/embassy-stm32-wpan/src/wb55/mac/control.rs b/embassy-stm32-wpan/src/wb55/mac/control.rs
new file mode 100644
index 000000000..14c6fdd2b
--- /dev/null
+++ b/embassy-stm32-wpan/src/wb55/mac/control.rs
@@ -0,0 +1,204 @@
1use core::cell::RefCell;
2use core::future::Future;
3use core::sync::atomic::{Ordering, compiler_fence};
4use core::task;
5use core::task::Poll;
6
7use embassy_net_driver::LinkState;
8use embassy_sync::blocking_mutex;
9use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
10use embassy_sync::mutex::Mutex;
11use embassy_sync::signal::Signal;
12use futures_util::FutureExt;
13
14use crate::mac::commands::*;
15use crate::mac::driver::NetworkState;
16use crate::mac::event::MacEvent;
17use crate::mac::runner::ZeroCopyPubSub;
18use crate::mac::typedefs::*;
19use crate::sub::mac::MacTx;
20
21pub struct Control<'a> {
22 rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>,
23 mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx<'a>>,
24 #[allow(unused)]
25 network_state: &'a blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>,
26}
27
28impl<'a> Control<'a> {
29 pub(crate) fn new(
30 rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>,
31 mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx<'a>>,
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, 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 let (short_address, mac_address) = critical_section::with(|cs| {
56 let mut network_state = self.network_state.borrow(cs).borrow_mut();
57
58 network_state.pan_id = pan_id;
59
60 (network_state.short_addr, network_state.mac_addr)
61 });
62
63 debug!("setting extended address");
64 debug!(
65 "{:#x}",
66 self.send_command_and_get_response(&SetRequest {
67 pib_attribute_ptr: &u64::from_be_bytes(mac_address) as *const _ as *const u8,
68 pib_attribute: PibId::ExtendedAddress,
69 })
70 .await
71 .unwrap()
72 .await
73 );
74
75 debug!("setting short address");
76 debug!(
77 "{:#x}",
78 self.send_command_and_get_response(&SetRequest {
79 pib_attribute_ptr: &u16::from_be_bytes(short_address) as *const _ as *const u8,
80 pib_attribute: PibId::ShortAddress,
81 })
82 .await
83 .unwrap()
84 .await
85 );
86
87 debug!("setting association permit");
88 let association_permit: bool = true;
89 debug!(
90 "{:#x}",
91 self.send_command_and_get_response(&SetRequest {
92 pib_attribute_ptr: &association_permit as *const _ as *const u8,
93 pib_attribute: PibId::AssociationPermit,
94 })
95 .await
96 .unwrap()
97 .await
98 );
99
100 debug!("setting TX power");
101 let transmit_power: i8 = 2;
102 debug!(
103 "{:#x}",
104 self.send_command_and_get_response(&SetRequest {
105 pib_attribute_ptr: &transmit_power as *const _ as *const u8,
106 pib_attribute: PibId::TransmitPower,
107 })
108 .await
109 .unwrap()
110 .await
111 );
112
113 debug!("starting FFD device");
114 debug!(
115 "{:#x}",
116 self.send_command_and_get_response(&StartRequest {
117 pan_id: PanId(pan_id),
118 channel_number: MacChannel::Channel16,
119 beacon_order: 0x0F,
120 superframe_order: 0x0F,
121 pan_coordinator: true,
122 battery_life_extension: false,
123 ..Default::default()
124 })
125 .await
126 .unwrap()
127 .await
128 );
129
130 debug!("setting RX on when idle");
131 let rx_on_while_idle: bool = true;
132 debug!(
133 "{:#x}",
134 self.send_command_and_get_response(&SetRequest {
135 pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8,
136 pib_attribute: PibId::RxOnWhenIdle,
137 })
138 .await
139 .unwrap()
140 .await
141 );
142
143 critical_section::with(|cs| {
144 let mut network_state = self.network_state.borrow(cs).borrow_mut();
145
146 network_state.link_state = LinkState::Up;
147 network_state.link_waker.wake();
148 });
149 }
150
151 pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError>
152 where
153 T: MacCommand,
154 {
155 self.mac_tx.lock().await.send_command(cmd).await
156 }
157
158 pub async fn send_command_and_get_response<T>(&self, cmd: &T) -> Result<EventToken<'a>, MacError>
159 where
160 T: MacCommand,
161 {
162 let token = EventToken::new(self.rx_event_channel);
163
164 compiler_fence(Ordering::Release);
165
166 self.mac_tx.lock().await.send_command(cmd).await?;
167
168 Ok(token)
169 }
170}
171
172pub struct EventToken<'a> {
173 rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>,
174}
175
176impl<'a> EventToken<'a> {
177 pub(crate) fn new(rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>) -> Self {
178 // Enable event receiving
179 rx_event_channel.lock(|s| {
180 *s.borrow_mut() = Some(Signal::new());
181 });
182
183 Self { rx_event_channel }
184 }
185}
186
187impl<'a> Future for EventToken<'a> {
188 type Output = MacEvent<'a>;
189
190 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
191 self.rx_event_channel
192 .lock(|s| s.borrow_mut().as_mut().unwrap().wait().poll_unpin(cx))
193 }
194}
195
196impl<'a> Drop for EventToken<'a> {
197 fn drop(&mut self) {
198 // Disable event receiving
199 // This will also drop the contained event, if it exists, and will free up receiving the next event
200 self.rx_event_channel.lock(|s| {
201 *s.borrow_mut() = None;
202 });
203 }
204}