diff options
Diffstat (limited to 'embassy-stm32-wpan')
| -rw-r--r-- | embassy-stm32-wpan/Cargo.toml | 1 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/control.rs | 171 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/driver.rs | 120 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/mod.rs | 6 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/runner.rs | 73 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/sub/mac.rs | 83 |
6 files changed, 354 insertions, 100 deletions
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 } | |||
| 40 | cortex-m = "0.7.6" | 40 | cortex-m = "0.7.6" |
| 41 | heapless = "0.8" | 41 | heapless = "0.8" |
| 42 | aligned = "0.4.1" | 42 | aligned = "0.4.1" |
| 43 | critical-section = "1.1" | ||
| 43 | 44 | ||
| 44 | bit_field = "0.10.2" | 45 | bit_field = "0.10.2" |
| 45 | stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } | 46 | stm32-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..fae00c6dc 100644 --- a/embassy-stm32-wpan/src/mac/control.rs +++ b/embassy-stm32-wpan/src/mac/control.rs | |||
| @@ -1,65 +1,186 @@ | |||
| 1 | use core::cell::RefCell; | ||
| 1 | use core::future::Future; | 2 | use core::future::Future; |
| 3 | use core::sync::atomic::{Ordering, compiler_fence}; | ||
| 2 | use core::task; | 4 | use core::task; |
| 3 | use core::task::Poll; | 5 | use core::task::Poll; |
| 4 | 6 | ||
| 7 | use embassy_net_driver::LinkState; | ||
| 8 | use embassy_sync::blocking_mutex; | ||
| 5 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 9 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 6 | use embassy_sync::mutex::MutexGuard; | 10 | use embassy_sync::mutex::Mutex; |
| 7 | use embassy_sync::signal::Signal; | 11 | use embassy_sync::signal::Signal; |
| 8 | use futures_util::FutureExt; | 12 | use futures_util::FutureExt; |
| 9 | 13 | ||
| 10 | use super::commands::MacCommand; | 14 | use crate::mac::commands::MacCommand; |
| 11 | use super::event::MacEvent; | 15 | use crate::mac::commands::*; |
| 12 | use super::typedefs::MacError; | 16 | use crate::mac::driver::NetworkState; |
| 13 | use crate::mac::runner::Runner; | 17 | use crate::mac::event::MacEvent; |
| 18 | use crate::mac::runner::ZeroCopyPubSub; | ||
| 19 | use crate::mac::typedefs::MacError; | ||
| 20 | use crate::mac::typedefs::*; | ||
| 21 | use crate::sub::mac::MacTx; | ||
| 14 | 22 | ||
| 15 | pub struct Control<'a> { | 23 | pub struct Control<'a> { |
| 16 | runner: &'a Runner<'a>, | 24 | rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>, |
| 25 | mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx>, | ||
| 26 | #[allow(unused)] | ||
| 27 | network_state: &'a blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>, | ||
| 17 | } | 28 | } |
| 18 | 29 | ||
| 19 | impl<'a> Control<'a> { | 30 | impl<'a> Control<'a> { |
| 20 | pub(crate) fn new(runner: &'a Runner<'a>) -> Self { | 31 | pub(crate) fn new( |
| 21 | Self { runner: runner } | 32 | rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>, |
| 33 | mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx>, | ||
| 34 | network_state: &'a blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>, | ||
| 35 | ) -> Self { | ||
| 36 | Self { | ||
| 37 | rx_event_channel, | ||
| 38 | mac_tx, | ||
| 39 | network_state, | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | pub async fn init_link(&mut self, short_address: [u8; 2], extended_address: [u8; 8], pan_id: [u8; 2]) { | ||
| 44 | debug!("resetting"); | ||
| 45 | |||
| 46 | debug!( | ||
| 47 | "{:#x}", | ||
| 48 | self.send_command_and_get_response(&ResetRequest { | ||
| 49 | set_default_pib: true, | ||
| 50 | ..Default::default() | ||
| 51 | }) | ||
| 52 | .await | ||
| 53 | .unwrap() | ||
| 54 | .await | ||
| 55 | ); | ||
| 56 | |||
| 57 | debug!("setting extended address"); | ||
| 58 | let extended_address: u64 = u64::from_be_bytes(extended_address); | ||
| 59 | debug!( | ||
| 60 | "{:#x}", | ||
| 61 | self.send_command_and_get_response(&SetRequest { | ||
| 62 | pib_attribute_ptr: &extended_address as *const _ as *const u8, | ||
| 63 | pib_attribute: PibId::ExtendedAddress, | ||
| 64 | }) | ||
| 65 | .await | ||
| 66 | .unwrap() | ||
| 67 | .await | ||
| 68 | ); | ||
| 69 | |||
| 70 | debug!("setting short address"); | ||
| 71 | let short_address: u16 = u16::from_be_bytes(short_address); | ||
| 72 | debug!( | ||
| 73 | "{:#x}", | ||
| 74 | self.send_command_and_get_response(&SetRequest { | ||
| 75 | pib_attribute_ptr: &short_address as *const _ as *const u8, | ||
| 76 | pib_attribute: PibId::ShortAddress, | ||
| 77 | }) | ||
| 78 | .await | ||
| 79 | .unwrap() | ||
| 80 | .await | ||
| 81 | ); | ||
| 82 | |||
| 83 | critical_section::with(|cs| { | ||
| 84 | self.network_state.borrow(cs).borrow_mut().mac_addr = extended_address.to_be_bytes(); | ||
| 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 | }); | ||
| 22 | } | 149 | } |
| 23 | 150 | ||
| 24 | pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError> | 151 | pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError> |
| 25 | where | 152 | where |
| 26 | T: MacCommand, | 153 | T: MacCommand, |
| 27 | { | 154 | { |
| 28 | let _wm = self.runner.write_mutex.lock().await; | 155 | self.mac_tx.lock().await.send_command(cmd).await |
| 29 | |||
| 30 | self.runner.mac_subsystem.send_command(cmd).await | ||
| 31 | } | 156 | } |
| 32 | 157 | ||
| 33 | pub async fn send_command_and_get_response<T>(&self, cmd: &T) -> Result<EventToken<'a>, MacError> | 158 | pub async fn send_command_and_get_response<T>(&self, cmd: &T) -> Result<EventToken<'a>, MacError> |
| 34 | where | 159 | where |
| 35 | T: MacCommand, | 160 | T: MacCommand, |
| 36 | { | 161 | { |
| 37 | let rm = self.runner.read_mutex.lock().await; | 162 | let token = EventToken::new(self.rx_event_channel); |
| 38 | let _wm = self.runner.write_mutex.lock().await; | 163 | |
| 39 | let token = EventToken::new(self.runner, rm); | 164 | compiler_fence(Ordering::Release); |
| 40 | 165 | ||
| 41 | self.runner.mac_subsystem.send_command(cmd).await?; | 166 | self.mac_tx.lock().await.send_command(cmd).await?; |
| 42 | 167 | ||
| 43 | Ok(token) | 168 | Ok(token) |
| 44 | } | 169 | } |
| 45 | } | 170 | } |
| 46 | 171 | ||
| 47 | pub struct EventToken<'a> { | 172 | pub struct EventToken<'a> { |
| 48 | runner: &'a Runner<'a>, | 173 | rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>, |
| 49 | _mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>, | ||
| 50 | } | 174 | } |
| 51 | 175 | ||
| 52 | impl<'a> EventToken<'a> { | 176 | impl<'a> EventToken<'a> { |
| 53 | pub(crate) fn new(runner: &'a Runner<'a>, mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>) -> Self { | 177 | pub(crate) fn new(rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>) -> Self { |
| 54 | // Enable event receiving | 178 | // Enable event receiving |
| 55 | runner.rx_event_channel.lock(|s| { | 179 | rx_event_channel.lock(|s| { |
| 56 | *s.borrow_mut() = Some(Signal::new()); | 180 | *s.borrow_mut() = Some(Signal::new()); |
| 57 | }); | 181 | }); |
| 58 | 182 | ||
| 59 | Self { | 183 | Self { rx_event_channel } |
| 60 | runner: runner, | ||
| 61 | _mutex_guard: mutex_guard, | ||
| 62 | } | ||
| 63 | } | 184 | } |
| 64 | } | 185 | } |
| 65 | 186 | ||
| @@ -67,7 +188,7 @@ impl<'a> Future for EventToken<'a> { | |||
| 67 | type Output = MacEvent<'a>; | 188 | type Output = MacEvent<'a>; |
| 68 | 189 | ||
| 69 | fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | 190 | 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| { | 191 | self.rx_event_channel.lock(|s| { |
| 71 | let signal = s.borrow_mut(); | 192 | let signal = s.borrow_mut(); |
| 72 | let signal = match &*signal { | 193 | let signal = match &*signal { |
| 73 | Some(s) => s, | 194 | Some(s) => s, |
| @@ -88,7 +209,7 @@ impl<'a> Drop for EventToken<'a> { | |||
| 88 | fn drop(&mut self) { | 209 | fn drop(&mut self) { |
| 89 | // Disable event receiving | 210 | // Disable event receiving |
| 90 | // This will also drop the contained event, if it exists, and will free up receiving the next event | 211 | // 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| { | 212 | self.rx_event_channel.lock(|s| { |
| 92 | *s.borrow_mut() = None; | 213 | *s.borrow_mut() = None; |
| 93 | }); | 214 | }); |
| 94 | } | 215 | } |
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 | ||
| 3 | use core::cell::RefCell; | ||
| 3 | use core::task::Context; | 4 | use core::task::Context; |
| 4 | 5 | ||
| 5 | use embassy_net_driver::{Capabilities, HardwareAddress, LinkState}; | 6 | use embassy_net_driver::{Capabilities, HardwareAddress, LinkState}; |
| 7 | use embassy_sync::blocking_mutex; | ||
| 6 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 8 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 7 | use embassy_sync::channel::Channel; | 9 | use embassy_sync::channel::Channel; |
| 10 | use embassy_sync::mutex::Mutex; | ||
| 11 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 8 | 12 | ||
| 9 | use crate::mac::MTU; | ||
| 10 | use crate::mac::event::MacEvent; | 13 | use crate::mac::event::MacEvent; |
| 11 | use crate::mac::runner::Runner; | 14 | use crate::mac::runner::{BUF_SIZE, ZeroCopyPubSub}; |
| 15 | use crate::mac::{Control, MTU, Runner}; | ||
| 16 | use crate::sub::mac::{Mac, MacRx, MacTx}; | ||
| 17 | |||
| 18 | pub struct NetworkState { | ||
| 19 | pub mac_addr: [u8; 8], | ||
| 20 | pub link_state: LinkState, | ||
| 21 | pub link_waker: AtomicWaker, | ||
| 22 | } | ||
| 23 | |||
| 24 | impl 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 | |||
| 34 | pub 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 | |||
| 45 | impl<'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 | ||
| 13 | pub struct Driver<'d> { | 63 | pub 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 | ||
| 17 | impl<'d> Driver<'d> { | 70 | impl<'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 | ||
| 101 | pub struct TxToken<'d> { | 183 | pub 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 | ||
| 106 | impl<'d> embassy_net_driver::TxToken for TxToken<'d> { | 188 | impl<'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; | |||
| 11 | pub mod typedefs; | 11 | pub mod typedefs; |
| 12 | 12 | ||
| 13 | pub use crate::mac::control::Control; | 13 | pub use crate::mac::control::Control; |
| 14 | use crate::mac::driver::Driver; | 14 | pub use crate::mac::driver::{Driver, DriverState}; |
| 15 | pub use crate::mac::runner::Runner; | 15 | pub use crate::mac::runner::Runner; |
| 16 | 16 | ||
| 17 | const MTU: usize = 127; | 17 | const MTU: usize = 127; |
| 18 | |||
| 19 | pub 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; | |||
| 8 | use embassy_sync::signal::Signal; | 8 | use embassy_sync::signal::Signal; |
| 9 | 9 | ||
| 10 | use crate::mac::MTU; | 10 | use crate::mac::MTU; |
| 11 | use crate::mac::commands::DataRequest; | 11 | use crate::mac::commands::*; |
| 12 | use crate::mac::driver::NetworkState; | ||
| 12 | use crate::mac::event::MacEvent; | 13 | use crate::mac::event::MacEvent; |
| 13 | use crate::mac::typedefs::{AddressMode, MacAddress, PanId, SecurityLevel}; | 14 | use crate::mac::typedefs::*; |
| 14 | use crate::sub::mac::Mac; | 15 | use crate::sub::mac::{MacRx, MacTx}; |
| 15 | 16 | ||
| 16 | type ZeroCopyPubSub<M, T> = blocking_mutex::Mutex<M, RefCell<Option<Signal<NoopRawMutex, T>>>>; | 17 | pub type ZeroCopyPubSub<M, T> = blocking_mutex::Mutex<M, RefCell<Option<Signal<NoopRawMutex, T>>>>; |
| 18 | |||
| 19 | pub const BUF_SIZE: usize = 3; | ||
| 17 | 20 | ||
| 18 | pub struct Runner<'a> { | 21 | pub 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 | ||
| 30 | impl<'a> Runner<'a> { | 36 | impl<'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 | |||
| 59 | pub struct MacTx { | ||
| 60 | _private: (), | ||
| 61 | } | ||
| 62 | |||
| 63 | impl 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 | |||
| 104 | pub struct MacRx { | ||
| 105 | _private: (), | ||
| 106 | } | ||
| 107 | |||
| 108 | impl 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) |
