diff options
Diffstat (limited to 'embassy-stm32-wpan/src/wb55/mac/runner.rs')
| -rw-r--r-- | embassy-stm32-wpan/src/wb55/mac/runner.rs | 151 |
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 @@ | |||
| 1 | use core::cell::RefCell; | ||
| 2 | |||
| 3 | use embassy_futures::join; | ||
| 4 | use embassy_sync::blocking_mutex; | ||
| 5 | use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; | ||
| 6 | use embassy_sync::channel::Channel; | ||
| 7 | use embassy_sync::mutex::Mutex; | ||
| 8 | use embassy_sync::signal::Signal; | ||
| 9 | use smoltcp::wire::Ieee802154FrameType; | ||
| 10 | use smoltcp::wire::ieee802154::Frame; | ||
| 11 | |||
| 12 | use crate::mac::MTU; | ||
| 13 | use crate::mac::commands::*; | ||
| 14 | use crate::mac::driver::NetworkState; | ||
| 15 | use crate::mac::event::MacEvent; | ||
| 16 | use crate::sub::mac::{MacRx, MacTx}; | ||
| 17 | |||
| 18 | pub type ZeroCopyPubSub<M, T> = blocking_mutex::Mutex<M, RefCell<Option<Signal<NoopRawMutex, T>>>>; | ||
| 19 | |||
| 20 | pub const BUF_SIZE: usize = 3; | ||
| 21 | |||
| 22 | pub 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 | |||
| 37 | impl<'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 | } | ||
