diff options
| author | xoviat <[email protected]> | 2023-07-21 22:29:15 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-07-21 22:29:15 +0000 |
| commit | 4db63677f6e56c52ea3d432542513967f5d93c69 (patch) | |
| tree | ad109082d957fced3b0e9a33ba74f3a47ea1da54 | |
| parent | 4d1d125f4157084668a949f9bc24e4417628f9fe (diff) | |
| parent | f4d6a23f92c8f6d3eb97a09e5bc51bac5e8d6837 (diff) | |
Merge pull request #1658 from xoviat/mac
implement most infra for wpan mac
| -rw-r--r-- | embassy-net-driver/src/lib.rs | 3 | ||||
| -rw-r--r-- | embassy-net/Cargo.toml | 1 | ||||
| -rw-r--r-- | embassy-net/src/device.rs | 2 | ||||
| -rw-r--r-- | embassy-net/src/lib.rs | 13 | ||||
| -rw-r--r-- | embassy-stm32-wpan/Cargo.toml | 4 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/lib.rs | 3 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/control.rs | 95 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/driver.rs | 122 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/event.rs | 159 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/indications.rs | 14 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/mod.rs | 13 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/responses.rs | 21 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/runner.rs | 109 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/typedefs.rs | 32 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/sub/mac.rs | 10 | ||||
| -rw-r--r-- | embassy-sync/src/channel.rs | 22 | ||||
| -rw-r--r-- | examples/stm32wb/Cargo.toml | 9 | ||||
| -rw-r--r-- | examples/stm32wb/src/bin/mac_ffd.rs | 37 | ||||
| -rw-r--r-- | examples/stm32wb/src/bin/mac_ffd_net.rs | 170 | ||||
| -rw-r--r-- | examples/stm32wb/src/bin/mac_rfd.rs | 36 | ||||
| -rw-r--r-- | tests/stm32/src/bin/wpan_mac.rs | 26 |
21 files changed, 764 insertions, 137 deletions
diff --git a/embassy-net-driver/src/lib.rs b/embassy-net-driver/src/lib.rs index 4149bf4a4..09def20c4 100644 --- a/embassy-net-driver/src/lib.rs +++ b/embassy-net-driver/src/lib.rs | |||
| @@ -164,6 +164,9 @@ pub enum Medium { | |||
| 164 | /// | 164 | /// |
| 165 | /// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode. | 165 | /// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode. |
| 166 | Ip, | 166 | Ip, |
| 167 | |||
| 168 | /// IEEE 802_15_4 medium | ||
| 169 | Ieee802154, | ||
| 167 | } | 170 | } |
| 168 | 171 | ||
| 169 | impl Default for Medium { | 172 | impl Default for Medium { |
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index 6dc429ddc..9b6a11c16 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml | |||
| @@ -37,6 +37,7 @@ proto-ipv4 = ["smoltcp/proto-ipv4"] | |||
| 37 | proto-ipv6 = ["smoltcp/proto-ipv6"] | 37 | proto-ipv6 = ["smoltcp/proto-ipv6"] |
| 38 | medium-ethernet = ["smoltcp/medium-ethernet"] | 38 | medium-ethernet = ["smoltcp/medium-ethernet"] |
| 39 | medium-ip = ["smoltcp/medium-ip"] | 39 | medium-ip = ["smoltcp/medium-ip"] |
| 40 | medium-ieee802154 = ["smoltcp/medium-ieee802154"] | ||
| 40 | igmp = ["smoltcp/proto-igmp"] | 41 | igmp = ["smoltcp/proto-igmp"] |
| 41 | 42 | ||
| 42 | [dependencies] | 43 | [dependencies] |
diff --git a/embassy-net/src/device.rs b/embassy-net/src/device.rs index 4513c86d3..d29ab8970 100644 --- a/embassy-net/src/device.rs +++ b/embassy-net/src/device.rs | |||
| @@ -51,6 +51,8 @@ where | |||
| 51 | Medium::Ethernet => phy::Medium::Ethernet, | 51 | Medium::Ethernet => phy::Medium::Ethernet, |
| 52 | #[cfg(feature = "medium-ip")] | 52 | #[cfg(feature = "medium-ip")] |
| 53 | Medium::Ip => phy::Medium::Ip, | 53 | Medium::Ip => phy::Medium::Ip, |
| 54 | #[cfg(feature = "medium-ieee802154")] | ||
| 55 | Medium::Ieee802154 => phy::Medium::Ieee802154, | ||
| 54 | #[allow(unreachable_patterns)] | 56 | #[allow(unreachable_patterns)] |
| 55 | _ => panic!( | 57 | _ => panic!( |
| 56 | "Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.", | 58 | "Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.", |
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 4fbafe752..81c751a2c 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs | |||
| @@ -24,9 +24,11 @@ use embassy_net_driver::{Driver, LinkState, Medium}; | |||
| 24 | use embassy_sync::waitqueue::WakerRegistration; | 24 | use embassy_sync::waitqueue::WakerRegistration; |
| 25 | use embassy_time::{Instant, Timer}; | 25 | use embassy_time::{Instant, Timer}; |
| 26 | use futures::pin_mut; | 26 | use futures::pin_mut; |
| 27 | #[allow(unused_imports)] | ||
| 27 | use heapless::Vec; | 28 | use heapless::Vec; |
| 28 | #[cfg(feature = "igmp")] | 29 | #[cfg(feature = "igmp")] |
| 29 | pub use smoltcp::iface::MulticastError; | 30 | pub use smoltcp::iface::MulticastError; |
| 31 | #[allow(unused_imports)] | ||
| 30 | use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage}; | 32 | use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage}; |
| 31 | #[cfg(feature = "dhcpv4")] | 33 | #[cfg(feature = "dhcpv4")] |
| 32 | use smoltcp::socket::dhcpv4::{self, RetryConfig}; | 34 | use smoltcp::socket::dhcpv4::{self, RetryConfig}; |
| @@ -34,6 +36,8 @@ use smoltcp::socket::dhcpv4::{self, RetryConfig}; | |||
| 34 | pub use smoltcp::wire::IpListenEndpoint; | 36 | pub use smoltcp::wire::IpListenEndpoint; |
| 35 | #[cfg(feature = "medium-ethernet")] | 37 | #[cfg(feature = "medium-ethernet")] |
| 36 | pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; | 38 | pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; |
| 39 | #[cfg(feature = "medium-ieee802154")] | ||
| 40 | pub use smoltcp::wire::{HardwareAddress, Ieee802154Address}; | ||
| 37 | pub use smoltcp::wire::{IpAddress, IpCidr, IpEndpoint}; | 41 | pub use smoltcp::wire::{IpAddress, IpCidr, IpEndpoint}; |
| 38 | #[cfg(feature = "proto-ipv4")] | 42 | #[cfg(feature = "proto-ipv4")] |
| 39 | pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr}; | 43 | pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr}; |
| @@ -232,7 +236,7 @@ impl<D: Driver + 'static> Stack<D> { | |||
| 232 | resources: &'static mut StackResources<SOCK>, | 236 | resources: &'static mut StackResources<SOCK>, |
| 233 | random_seed: u64, | 237 | random_seed: u64, |
| 234 | ) -> Self { | 238 | ) -> Self { |
| 235 | #[cfg(feature = "medium-ethernet")] | 239 | #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] |
| 236 | let medium = device.capabilities().medium; | 240 | let medium = device.capabilities().medium; |
| 237 | 241 | ||
| 238 | let hardware_addr = match medium { | 242 | let hardware_addr = match medium { |
| @@ -240,6 +244,8 @@ impl<D: Driver + 'static> Stack<D> { | |||
| 240 | Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress(device.ethernet_address())), | 244 | Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress(device.ethernet_address())), |
| 241 | #[cfg(feature = "medium-ip")] | 245 | #[cfg(feature = "medium-ip")] |
| 242 | Medium::Ip => HardwareAddress::Ip, | 246 | Medium::Ip => HardwareAddress::Ip, |
| 247 | #[cfg(feature = "medium-ieee802154")] | ||
| 248 | Medium::Ieee802154 => HardwareAddress::Ieee802154(Ieee802154Address::Absent), | ||
| 243 | #[allow(unreachable_patterns)] | 249 | #[allow(unreachable_patterns)] |
| 244 | _ => panic!( | 250 | _ => panic!( |
| 245 | "Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.", | 251 | "Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.", |
| @@ -262,6 +268,7 @@ impl<D: Driver + 'static> Stack<D> { | |||
| 262 | 268 | ||
| 263 | let next_local_port = (random_seed % (LOCAL_PORT_MAX - LOCAL_PORT_MIN) as u64) as u16 + LOCAL_PORT_MIN; | 269 | let next_local_port = (random_seed % (LOCAL_PORT_MAX - LOCAL_PORT_MIN) as u64) as u16 + LOCAL_PORT_MIN; |
| 264 | 270 | ||
| 271 | #[cfg_attr(feature = "medium-ieee802154", allow(unused_mut))] | ||
| 265 | let mut socket = SocketStack { | 272 | let mut socket = SocketStack { |
| 266 | sockets, | 273 | sockets, |
| 267 | iface, | 274 | iface, |
| @@ -269,6 +276,7 @@ impl<D: Driver + 'static> Stack<D> { | |||
| 269 | next_local_port, | 276 | next_local_port, |
| 270 | }; | 277 | }; |
| 271 | 278 | ||
| 279 | #[cfg_attr(feature = "medium-ieee802154", allow(unused_mut))] | ||
| 272 | let mut inner = Inner { | 280 | let mut inner = Inner { |
| 273 | device, | 281 | device, |
| 274 | link_up: false, | 282 | link_up: false, |
| @@ -287,6 +295,9 @@ impl<D: Driver + 'static> Stack<D> { | |||
| 287 | dns_waker: WakerRegistration::new(), | 295 | dns_waker: WakerRegistration::new(), |
| 288 | }; | 296 | }; |
| 289 | 297 | ||
| 298 | #[cfg(feature = "medium-ieee802154")] | ||
| 299 | let _ = config; | ||
| 300 | |||
| 290 | #[cfg(feature = "proto-ipv4")] | 301 | #[cfg(feature = "proto-ipv4")] |
| 291 | match config.ipv4 { | 302 | match config.ipv4 { |
| 292 | ConfigV4::Static(config) => { | 303 | ConfigV4::Static(config) => { |
diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 868bffe74..6cd122200 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml | |||
| @@ -17,6 +17,7 @@ embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } | |||
| 17 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } | 17 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } |
| 18 | embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } | 18 | embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } |
| 19 | embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } | 19 | embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } |
| 20 | embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver", optional=true } | ||
| 20 | 21 | ||
| 21 | defmt = { version = "0.3", optional = true } | 22 | defmt = { version = "0.3", optional = true } |
| 22 | cortex-m = "0.7.6" | 23 | cortex-m = "0.7.6" |
| @@ -26,13 +27,14 @@ aligned = "0.4.1" | |||
| 26 | bit_field = "0.10.2" | 27 | bit_field = "0.10.2" |
| 27 | stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } | 28 | stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } |
| 28 | stm32wb-hci = { version = "0.1.3", optional = true } | 29 | stm32wb-hci = { version = "0.1.3", optional = true } |
| 30 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | ||
| 29 | bitflags = { version = "2.3.3", optional = true } | 31 | bitflags = { version = "2.3.3", optional = true } |
| 30 | 32 | ||
| 31 | [features] | 33 | [features] |
| 32 | defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"] | 34 | defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"] |
| 33 | 35 | ||
| 34 | ble = ["dep:stm32wb-hci"] | 36 | ble = ["dep:stm32wb-hci"] |
| 35 | mac = ["dep:bitflags"] | 37 | mac = ["dep:bitflags", "dep:embassy-net-driver" ] |
| 36 | 38 | ||
| 37 | stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] | 39 | stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] |
| 38 | stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] | 40 | stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] |
diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index 57f0dc4fa..6836d7a8b 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![cfg_attr(feature = "ble", feature(async_fn_in_trait))] | 2 | #![cfg_attr(any(feature = "ble", feature = "mac"), feature(async_fn_in_trait))] |
| 3 | #![cfg_attr(feature = "mac", feature(type_alias_impl_trait, concat_bytes))] | ||
| 3 | 4 | ||
| 4 | // This must go FIRST so that all the other modules see its macros. | 5 | // This must go FIRST so that all the other modules see its macros. |
| 5 | pub mod fmt; | 6 | pub mod fmt; |
diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs new file mode 100644 index 000000000..8a13de81c --- /dev/null +++ b/embassy-stm32-wpan/src/mac/control.rs | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | use core::future::Future; | ||
| 2 | use core::task; | ||
| 3 | use core::task::Poll; | ||
| 4 | |||
| 5 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 6 | use embassy_sync::mutex::MutexGuard; | ||
| 7 | use embassy_sync::signal::Signal; | ||
| 8 | use futures::FutureExt; | ||
| 9 | |||
| 10 | use super::commands::MacCommand; | ||
| 11 | use super::event::MacEvent; | ||
| 12 | use super::typedefs::MacError; | ||
| 13 | use crate::mac::runner::Runner; | ||
| 14 | |||
| 15 | pub struct Control<'a> { | ||
| 16 | runner: &'a Runner<'a>, | ||
| 17 | } | ||
| 18 | |||
| 19 | impl<'a> Control<'a> { | ||
| 20 | pub(crate) fn new(runner: &'a Runner<'a>) -> Self { | ||
| 21 | Self { runner: runner } | ||
| 22 | } | ||
| 23 | |||
| 24 | pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError> | ||
| 25 | where | ||
| 26 | T: MacCommand, | ||
| 27 | { | ||
| 28 | let _wm = self.runner.write_mutex.lock().await; | ||
| 29 | |||
| 30 | self.runner.mac_subsystem.send_command(cmd).await | ||
| 31 | } | ||
| 32 | |||
| 33 | pub async fn send_command_and_get_response<T>(&self, cmd: &T) -> Result<EventToken<'a>, MacError> | ||
| 34 | where | ||
| 35 | T: MacCommand, | ||
| 36 | { | ||
| 37 | let rm = self.runner.read_mutex.lock().await; | ||
| 38 | let _wm = self.runner.write_mutex.lock().await; | ||
| 39 | let token = EventToken::new(self.runner, rm); | ||
| 40 | |||
| 41 | self.runner.mac_subsystem.send_command(cmd).await?; | ||
| 42 | |||
| 43 | Ok(token) | ||
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | pub struct EventToken<'a> { | ||
| 48 | runner: &'a Runner<'a>, | ||
| 49 | _mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>, | ||
| 50 | } | ||
| 51 | |||
| 52 | impl<'a> EventToken<'a> { | ||
| 53 | pub(crate) fn new(runner: &'a Runner<'a>, mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>) -> Self { | ||
| 54 | // Enable event receiving | ||
| 55 | runner.rx_event_channel.lock(|s| { | ||
| 56 | *s.borrow_mut() = Some(Signal::new()); | ||
| 57 | }); | ||
| 58 | |||
| 59 | Self { | ||
| 60 | runner: runner, | ||
| 61 | _mutex_guard: mutex_guard, | ||
| 62 | } | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | impl<'a> Future for EventToken<'a> { | ||
| 67 | type Output = MacEvent<'a>; | ||
| 68 | |||
| 69 | 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| { | ||
| 71 | let signal = s.borrow_mut(); | ||
| 72 | let signal = match &*signal { | ||
| 73 | Some(s) => s, | ||
| 74 | _ => unreachable!(), | ||
| 75 | }; | ||
| 76 | |||
| 77 | let result = match signal.wait().poll_unpin(cx) { | ||
| 78 | Poll::Ready(mac_event) => Poll::Ready(mac_event), | ||
| 79 | Poll::Pending => Poll::Pending, | ||
| 80 | }; | ||
| 81 | |||
| 82 | result | ||
| 83 | }) | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | impl<'a> Drop for EventToken<'a> { | ||
| 88 | fn drop(&mut self) { | ||
| 89 | // Disable event receiving | ||
| 90 | // 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| { | ||
| 92 | *s.borrow_mut() = None; | ||
| 93 | }); | ||
| 94 | } | ||
| 95 | } | ||
diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs new file mode 100644 index 000000000..fffbb9edc --- /dev/null +++ b/embassy-stm32-wpan/src/mac/driver.rs | |||
| @@ -0,0 +1,122 @@ | |||
| 1 | #![allow(incomplete_features)] | ||
| 2 | #![deny(unused_must_use)] | ||
| 3 | |||
| 4 | use core::task::Context; | ||
| 5 | |||
| 6 | use embassy_net_driver::{Capabilities, LinkState, Medium}; | ||
| 7 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 8 | use embassy_sync::channel::Channel; | ||
| 9 | |||
| 10 | use crate::mac::event::MacEvent; | ||
| 11 | use crate::mac::runner::Runner; | ||
| 12 | use crate::mac::MTU; | ||
| 13 | |||
| 14 | pub struct Driver<'d> { | ||
| 15 | runner: &'d Runner<'d>, | ||
| 16 | } | ||
| 17 | |||
| 18 | impl<'d> Driver<'d> { | ||
| 19 | pub(crate) fn new(runner: &'d Runner<'d>) -> Self { | ||
| 20 | Self { runner: runner } | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | impl<'d> embassy_net_driver::Driver for Driver<'d> { | ||
| 25 | // type RxToken<'a> = RxToken<'a, 'd> where Self: 'a; | ||
| 26 | // type TxToken<'a> = TxToken<'a, 'd> where Self: 'a; | ||
| 27 | type RxToken<'a> = RxToken<'d> where Self: 'a; | ||
| 28 | type TxToken<'a> = TxToken<'d> where Self: 'a; | ||
| 29 | |||
| 30 | fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { | ||
| 31 | if self.runner.rx_channel.poll_ready_to_receive(cx) && self.runner.tx_buf_channel.poll_ready_to_receive(cx) { | ||
| 32 | Some(( | ||
| 33 | RxToken { | ||
| 34 | rx: &self.runner.rx_channel, | ||
| 35 | }, | ||
| 36 | TxToken { | ||
| 37 | tx: &self.runner.tx_channel, | ||
| 38 | tx_buf: &self.runner.tx_buf_channel, | ||
| 39 | }, | ||
| 40 | )) | ||
| 41 | } else { | ||
| 42 | None | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> { | ||
| 47 | if self.runner.tx_buf_channel.poll_ready_to_receive(cx) { | ||
| 48 | Some(TxToken { | ||
| 49 | tx: &self.runner.tx_channel, | ||
| 50 | tx_buf: &self.runner.tx_buf_channel, | ||
| 51 | }) | ||
| 52 | } else { | ||
| 53 | None | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | fn capabilities(&self) -> Capabilities { | ||
| 58 | let mut caps = Capabilities::default(); | ||
| 59 | caps.max_transmission_unit = MTU; | ||
| 60 | // caps.max_burst_size = Some(self.tx.len()); | ||
| 61 | |||
| 62 | caps.medium = Medium::Ieee802154; | ||
| 63 | caps | ||
| 64 | } | ||
| 65 | |||
| 66 | fn link_state(&mut self, _cx: &mut Context) -> LinkState { | ||
| 67 | // if self.phy.poll_link(&mut self.station_management, cx) { | ||
| 68 | // LinkState::Up | ||
| 69 | // } else { | ||
| 70 | // LinkState::Down | ||
| 71 | // } | ||
| 72 | |||
| 73 | LinkState::Down | ||
| 74 | } | ||
| 75 | |||
| 76 | fn ethernet_address(&self) -> [u8; 6] { | ||
| 77 | // self.mac_addr | ||
| 78 | |||
| 79 | [0; 6] | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | pub struct RxToken<'d> { | ||
| 84 | rx: &'d Channel<CriticalSectionRawMutex, MacEvent<'d>, 1>, | ||
| 85 | } | ||
| 86 | |||
| 87 | impl<'d> embassy_net_driver::RxToken for RxToken<'d> { | ||
| 88 | fn consume<R, F>(self, f: F) -> R | ||
| 89 | where | ||
| 90 | F: FnOnce(&mut [u8]) -> R, | ||
| 91 | { | ||
| 92 | // Only valid data events should be put into the queue | ||
| 93 | |||
| 94 | let data_event = match self.rx.try_recv().unwrap() { | ||
| 95 | MacEvent::McpsDataInd(data_event) => data_event, | ||
| 96 | _ => unreachable!(), | ||
| 97 | }; | ||
| 98 | |||
| 99 | f(&mut data_event.payload()) | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | pub struct TxToken<'d> { | ||
| 104 | tx: &'d Channel<CriticalSectionRawMutex, (&'d mut [u8; MTU], usize), 5>, | ||
| 105 | tx_buf: &'d Channel<CriticalSectionRawMutex, &'d mut [u8; MTU], 5>, | ||
| 106 | } | ||
| 107 | |||
| 108 | impl<'d> embassy_net_driver::TxToken for TxToken<'d> { | ||
| 109 | fn consume<R, F>(self, len: usize, f: F) -> R | ||
| 110 | where | ||
| 111 | F: FnOnce(&mut [u8]) -> R, | ||
| 112 | { | ||
| 113 | // Only valid tx buffers should be put into the queue | ||
| 114 | let buf = self.tx_buf.try_recv().unwrap(); | ||
| 115 | let r = f(&mut buf[..len]); | ||
| 116 | |||
| 117 | // The tx channel should always be of equal capacity to the tx_buf channel | ||
| 118 | self.tx.try_send((buf, len)).unwrap(); | ||
| 119 | |||
| 120 | r | ||
| 121 | } | ||
| 122 | } | ||
diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs index a2bb79222..9ca4f5a2a 100644 --- a/embassy-stm32-wpan/src/mac/event.rs +++ b/embassy-stm32-wpan/src/mac/event.rs | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | use core::mem; | 1 | use core::{mem, ptr}; |
| 2 | 2 | ||
| 3 | use super::indications::{ | 3 | use super::indications::{ |
| 4 | AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication, | 4 | AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication, |
| @@ -8,9 +8,9 @@ use super::responses::{ | |||
| 8 | AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm, | 8 | AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm, |
| 9 | PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm, | 9 | PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm, |
| 10 | }; | 10 | }; |
| 11 | use crate::evt::EvtBox; | 11 | use crate::evt::{EvtBox, MemoryManager}; |
| 12 | use crate::mac::opcodes::OpcodeM0ToM4; | 12 | use crate::mac::opcodes::OpcodeM0ToM4; |
| 13 | use crate::sub::mac::Mac; | 13 | use crate::sub::mac::{self, Mac}; |
| 14 | 14 | ||
| 15 | pub(crate) trait ParseableMacEvent: Sized { | 15 | pub(crate) trait ParseableMacEvent: Sized { |
| 16 | fn from_buffer<'a>(buf: &'a [u8]) -> Result<&'a Self, ()> { | 16 | fn from_buffer<'a>(buf: &'a [u8]) -> Result<&'a Self, ()> { |
| @@ -22,59 +22,8 @@ pub(crate) trait ParseableMacEvent: Sized { | |||
| 22 | } | 22 | } |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | pub struct Event { | ||
| 26 | event_box: EvtBox<Mac>, | ||
| 27 | } | ||
| 28 | |||
| 29 | impl Event { | ||
| 30 | pub(crate) fn new(event_box: EvtBox<Mac>) -> Self { | ||
| 31 | Self { event_box } | ||
| 32 | } | ||
| 33 | |||
| 34 | pub fn mac_event<'a>(&'a self) -> Result<MacEvent<'a>, ()> { | ||
| 35 | let payload = self.event_box.payload(); | ||
| 36 | let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap()); | ||
| 37 | |||
| 38 | let opcode = OpcodeM0ToM4::try_from(opcode)?; | ||
| 39 | let buf = &payload[2..]; | ||
| 40 | |||
| 41 | match opcode { | ||
| 42 | OpcodeM0ToM4::MlmeAssociateCnf => Ok(MacEvent::MlmeAssociateCnf(AssociateConfirm::from_buffer(buf)?)), | ||
| 43 | OpcodeM0ToM4::MlmeDisassociateCnf => { | ||
| 44 | Ok(MacEvent::MlmeDisassociateCnf(DisassociateConfirm::from_buffer(buf)?)) | ||
| 45 | } | ||
| 46 | OpcodeM0ToM4::MlmeGetCnf => Ok(MacEvent::MlmeGetCnf(GetConfirm::from_buffer(buf)?)), | ||
| 47 | OpcodeM0ToM4::MlmeGtsCnf => Ok(MacEvent::MlmeGtsCnf(GtsConfirm::from_buffer(buf)?)), | ||
| 48 | OpcodeM0ToM4::MlmeResetCnf => Ok(MacEvent::MlmeResetCnf(ResetConfirm::from_buffer(buf)?)), | ||
| 49 | OpcodeM0ToM4::MlmeRxEnableCnf => Ok(MacEvent::MlmeRxEnableCnf(RxEnableConfirm::from_buffer(buf)?)), | ||
| 50 | OpcodeM0ToM4::MlmeScanCnf => Ok(MacEvent::MlmeScanCnf(ScanConfirm::from_buffer(buf)?)), | ||
| 51 | OpcodeM0ToM4::MlmeSetCnf => Ok(MacEvent::MlmeSetCnf(SetConfirm::from_buffer(buf)?)), | ||
| 52 | OpcodeM0ToM4::MlmeStartCnf => Ok(MacEvent::MlmeStartCnf(StartConfirm::from_buffer(buf)?)), | ||
| 53 | OpcodeM0ToM4::MlmePollCnf => Ok(MacEvent::MlmePollCnf(PollConfirm::from_buffer(buf)?)), | ||
| 54 | OpcodeM0ToM4::MlmeDpsCnf => Ok(MacEvent::MlmeDpsCnf(DpsConfirm::from_buffer(buf)?)), | ||
| 55 | OpcodeM0ToM4::MlmeSoundingCnf => Ok(MacEvent::MlmeSoundingCnf(SoundingConfirm::from_buffer(buf)?)), | ||
| 56 | OpcodeM0ToM4::MlmeCalibrateCnf => Ok(MacEvent::MlmeCalibrateCnf(CalibrateConfirm::from_buffer(buf)?)), | ||
| 57 | OpcodeM0ToM4::McpsDataCnf => Ok(MacEvent::McpsDataCnf(DataConfirm::from_buffer(buf)?)), | ||
| 58 | OpcodeM0ToM4::McpsPurgeCnf => Ok(MacEvent::McpsPurgeCnf(PurgeConfirm::from_buffer(buf)?)), | ||
| 59 | OpcodeM0ToM4::MlmeAssociateInd => Ok(MacEvent::MlmeAssociateInd(AssociateIndication::from_buffer(buf)?)), | ||
| 60 | OpcodeM0ToM4::MlmeDisassociateInd => { | ||
| 61 | Ok(MacEvent::MlmeDisassociateInd(DisassociateIndication::from_buffer(buf)?)) | ||
| 62 | } | ||
| 63 | OpcodeM0ToM4::MlmeBeaconNotifyInd => { | ||
| 64 | Ok(MacEvent::MlmeBeaconNotifyInd(BeaconNotifyIndication::from_buffer(buf)?)) | ||
| 65 | } | ||
| 66 | OpcodeM0ToM4::MlmeCommStatusInd => Ok(MacEvent::MlmeCommStatusInd(CommStatusIndication::from_buffer(buf)?)), | ||
| 67 | OpcodeM0ToM4::MlmeGtsInd => Ok(MacEvent::MlmeGtsInd(GtsIndication::from_buffer(buf)?)), | ||
| 68 | OpcodeM0ToM4::MlmeOrphanInd => Ok(MacEvent::MlmeOrphanInd(OrphanIndication::from_buffer(buf)?)), | ||
| 69 | OpcodeM0ToM4::MlmeSyncLossInd => Ok(MacEvent::MlmeSyncLossInd(SyncLossIndication::from_buffer(buf)?)), | ||
| 70 | OpcodeM0ToM4::MlmeDpsInd => Ok(MacEvent::MlmeDpsInd(DpsIndication::from_buffer(buf)?)), | ||
| 71 | OpcodeM0ToM4::McpsDataInd => Ok(MacEvent::McpsDataInd(DataIndication::from_buffer(buf)?)), | ||
| 72 | OpcodeM0ToM4::MlmePollInd => Ok(MacEvent::MlmePollInd(PollIndication::from_buffer(buf)?)), | ||
| 73 | } | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 25 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 26 | #[derive(Debug)] | ||
| 78 | pub enum MacEvent<'a> { | 27 | pub enum MacEvent<'a> { |
| 79 | MlmeAssociateCnf(&'a AssociateConfirm), | 28 | MlmeAssociateCnf(&'a AssociateConfirm), |
| 80 | MlmeDisassociateCnf(&'a DisassociateConfirm), | 29 | MlmeDisassociateCnf(&'a DisassociateConfirm), |
| @@ -102,3 +51,103 @@ pub enum MacEvent<'a> { | |||
| 102 | McpsDataInd(&'a DataIndication), | 51 | McpsDataInd(&'a DataIndication), |
| 103 | MlmePollInd(&'a PollIndication), | 52 | MlmePollInd(&'a PollIndication), |
| 104 | } | 53 | } |
| 54 | |||
| 55 | impl<'a> MacEvent<'a> { | ||
| 56 | pub(crate) fn new(event_box: EvtBox<Mac>) -> Result<Self, ()> { | ||
| 57 | let payload = event_box.payload(); | ||
| 58 | let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap()); | ||
| 59 | |||
| 60 | let opcode = OpcodeM0ToM4::try_from(opcode)?; | ||
| 61 | let buf = &payload[2..]; | ||
| 62 | |||
| 63 | // To avoid re-parsing the opcode, we store the result of the parse | ||
| 64 | // this requires use of unsafe because rust cannot assume that a reference will become | ||
| 65 | // invalid when the underlying result is moved. However, because we refer to a "heap" | ||
| 66 | // allocation, the underlying reference will not move until the struct is dropped. | ||
| 67 | |||
| 68 | let mac_event = match opcode { | ||
| 69 | OpcodeM0ToM4::MlmeAssociateCnf => { | ||
| 70 | MacEvent::MlmeAssociateCnf(unsafe { &*(AssociateConfirm::from_buffer(buf)? as *const _) }) | ||
| 71 | } | ||
| 72 | OpcodeM0ToM4::MlmeDisassociateCnf => { | ||
| 73 | MacEvent::MlmeDisassociateCnf(unsafe { &*(DisassociateConfirm::from_buffer(buf)? as *const _) }) | ||
| 74 | } | ||
| 75 | OpcodeM0ToM4::MlmeGetCnf => MacEvent::MlmeGetCnf(unsafe { &*(GetConfirm::from_buffer(buf)? as *const _) }), | ||
| 76 | OpcodeM0ToM4::MlmeGtsCnf => MacEvent::MlmeGtsCnf(unsafe { &*(GtsConfirm::from_buffer(buf)? as *const _) }), | ||
| 77 | OpcodeM0ToM4::MlmeResetCnf => { | ||
| 78 | MacEvent::MlmeResetCnf(unsafe { &*(ResetConfirm::from_buffer(buf)? as *const _) }) | ||
| 79 | } | ||
| 80 | OpcodeM0ToM4::MlmeRxEnableCnf => { | ||
| 81 | MacEvent::MlmeRxEnableCnf(unsafe { &*(RxEnableConfirm::from_buffer(buf)? as *const _) }) | ||
| 82 | } | ||
| 83 | OpcodeM0ToM4::MlmeScanCnf => { | ||
| 84 | MacEvent::MlmeScanCnf(unsafe { &*(ScanConfirm::from_buffer(buf)? as *const _) }) | ||
| 85 | } | ||
| 86 | OpcodeM0ToM4::MlmeSetCnf => MacEvent::MlmeSetCnf(unsafe { &*(SetConfirm::from_buffer(buf)? as *const _) }), | ||
| 87 | OpcodeM0ToM4::MlmeStartCnf => { | ||
| 88 | MacEvent::MlmeStartCnf(unsafe { &*(StartConfirm::from_buffer(buf)? as *const _) }) | ||
| 89 | } | ||
| 90 | OpcodeM0ToM4::MlmePollCnf => { | ||
| 91 | MacEvent::MlmePollCnf(unsafe { &*(PollConfirm::from_buffer(buf)? as *const _) }) | ||
| 92 | } | ||
| 93 | OpcodeM0ToM4::MlmeDpsCnf => MacEvent::MlmeDpsCnf(unsafe { &*(DpsConfirm::from_buffer(buf)? as *const _) }), | ||
| 94 | OpcodeM0ToM4::MlmeSoundingCnf => { | ||
| 95 | MacEvent::MlmeSoundingCnf(unsafe { &*(SoundingConfirm::from_buffer(buf)? as *const _) }) | ||
| 96 | } | ||
| 97 | OpcodeM0ToM4::MlmeCalibrateCnf => { | ||
| 98 | MacEvent::MlmeCalibrateCnf(unsafe { &*(CalibrateConfirm::from_buffer(buf)? as *const _) }) | ||
| 99 | } | ||
| 100 | OpcodeM0ToM4::McpsDataCnf => { | ||
| 101 | MacEvent::McpsDataCnf(unsafe { &*(DataConfirm::from_buffer(buf)? as *const _) }) | ||
| 102 | } | ||
| 103 | OpcodeM0ToM4::McpsPurgeCnf => { | ||
| 104 | MacEvent::McpsPurgeCnf(unsafe { &*(PurgeConfirm::from_buffer(buf)? as *const _) }) | ||
| 105 | } | ||
| 106 | OpcodeM0ToM4::MlmeAssociateInd => { | ||
| 107 | MacEvent::MlmeAssociateInd(unsafe { &*(AssociateIndication::from_buffer(buf)? as *const _) }) | ||
| 108 | } | ||
| 109 | OpcodeM0ToM4::MlmeDisassociateInd => { | ||
| 110 | MacEvent::MlmeDisassociateInd(unsafe { &*(DisassociateIndication::from_buffer(buf)? as *const _) }) | ||
| 111 | } | ||
| 112 | OpcodeM0ToM4::MlmeBeaconNotifyInd => { | ||
| 113 | MacEvent::MlmeBeaconNotifyInd(unsafe { &*(BeaconNotifyIndication::from_buffer(buf)? as *const _) }) | ||
| 114 | } | ||
| 115 | OpcodeM0ToM4::MlmeCommStatusInd => { | ||
| 116 | MacEvent::MlmeCommStatusInd(unsafe { &*(CommStatusIndication::from_buffer(buf)? as *const _) }) | ||
| 117 | } | ||
| 118 | OpcodeM0ToM4::MlmeGtsInd => { | ||
| 119 | MacEvent::MlmeGtsInd(unsafe { &*(GtsIndication::from_buffer(buf)? as *const _) }) | ||
| 120 | } | ||
| 121 | OpcodeM0ToM4::MlmeOrphanInd => { | ||
| 122 | MacEvent::MlmeOrphanInd(unsafe { &*(OrphanIndication::from_buffer(buf)? as *const _) }) | ||
| 123 | } | ||
| 124 | OpcodeM0ToM4::MlmeSyncLossInd => { | ||
| 125 | MacEvent::MlmeSyncLossInd(unsafe { &*(SyncLossIndication::from_buffer(buf)? as *const _) }) | ||
| 126 | } | ||
| 127 | OpcodeM0ToM4::MlmeDpsInd => { | ||
| 128 | MacEvent::MlmeDpsInd(unsafe { &*(DpsIndication::from_buffer(buf)? as *const _) }) | ||
| 129 | } | ||
| 130 | OpcodeM0ToM4::McpsDataInd => { | ||
| 131 | MacEvent::McpsDataInd(unsafe { &*(DataIndication::from_buffer(buf)? as *const _) }) | ||
| 132 | } | ||
| 133 | OpcodeM0ToM4::MlmePollInd => { | ||
| 134 | MacEvent::MlmePollInd(unsafe { &*(PollIndication::from_buffer(buf)? as *const _) }) | ||
| 135 | } | ||
| 136 | }; | ||
| 137 | |||
| 138 | // Forget the event box so that drop isn't called | ||
| 139 | // We want to handle the lifetime ourselves | ||
| 140 | |||
| 141 | mem::forget(event_box); | ||
| 142 | |||
| 143 | Ok(mac_event) | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | unsafe impl<'a> Send for MacEvent<'a> {} | ||
| 148 | |||
| 149 | impl<'a> Drop for MacEvent<'a> { | ||
| 150 | fn drop(&mut self) { | ||
| 151 | unsafe { mac::Mac::drop_event_packet(ptr::null_mut()) }; | ||
| 152 | } | ||
| 153 | } | ||
diff --git a/embassy-stm32-wpan/src/mac/indications.rs b/embassy-stm32-wpan/src/mac/indications.rs index 5445fb4af..c0b86d745 100644 --- a/embassy-stm32-wpan/src/mac/indications.rs +++ b/embassy-stm32-wpan/src/mac/indications.rs | |||
| @@ -10,6 +10,7 @@ use super::typedefs::{ | |||
| 10 | /// MLME ASSOCIATE Indication which will be used by the MAC | 10 | /// MLME ASSOCIATE Indication which will be used by the MAC |
| 11 | /// to indicate the reception of an association request command | 11 | /// to indicate the reception of an association request command |
| 12 | #[repr(C)] | 12 | #[repr(C)] |
| 13 | #[derive(Debug)] | ||
| 13 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 14 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 14 | pub struct AssociateIndication { | 15 | pub struct AssociateIndication { |
| 15 | /// Extended address of the device requesting association | 16 | /// Extended address of the device requesting association |
| @@ -31,6 +32,7 @@ impl ParseableMacEvent for AssociateIndication {} | |||
| 31 | /// MLME DISASSOCIATE indication which will be used to send | 32 | /// MLME DISASSOCIATE indication which will be used to send |
| 32 | /// disassociation indication to the application. | 33 | /// disassociation indication to the application. |
| 33 | #[repr(C)] | 34 | #[repr(C)] |
| 35 | #[derive(Debug)] | ||
| 34 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 36 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 35 | pub struct DisassociateIndication { | 37 | pub struct DisassociateIndication { |
| 36 | /// Extended address of the device requesting association | 38 | /// Extended address of the device requesting association |
| @@ -52,6 +54,7 @@ impl ParseableMacEvent for DisassociateIndication {} | |||
| 52 | /// MLME BEACON NOTIIFY Indication which is used to send parameters contained | 54 | /// MLME BEACON NOTIIFY Indication which is used to send parameters contained |
| 53 | /// within a beacon frame received by the MAC to the application | 55 | /// within a beacon frame received by the MAC to the application |
| 54 | #[repr(C)] | 56 | #[repr(C)] |
| 57 | #[derive(Debug)] | ||
| 55 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 58 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 56 | pub struct BeaconNotifyIndication { | 59 | pub struct BeaconNotifyIndication { |
| 57 | /// he set of octets comprising the beacon payload to be transferred | 60 | /// he set of octets comprising the beacon payload to be transferred |
| @@ -73,6 +76,7 @@ impl ParseableMacEvent for BeaconNotifyIndication {} | |||
| 73 | 76 | ||
| 74 | /// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status | 77 | /// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status |
| 75 | #[repr(C)] | 78 | #[repr(C)] |
| 79 | #[derive(Debug)] | ||
| 76 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 80 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 77 | pub struct CommStatusIndication { | 81 | pub struct CommStatusIndication { |
| 78 | /// The 16-bit PAN identifier of the device from which the frame | 82 | /// The 16-bit PAN identifier of the device from which the frame |
| @@ -103,6 +107,7 @@ impl ParseableMacEvent for CommStatusIndication {} | |||
| 103 | /// MLME GTS Indication indicates that a GTS has been allocated or that a | 107 | /// MLME GTS Indication indicates that a GTS has been allocated or that a |
| 104 | /// previously allocated GTS has been deallocated | 108 | /// previously allocated GTS has been deallocated |
| 105 | #[repr(C)] | 109 | #[repr(C)] |
| 110 | #[derive(Debug)] | ||
| 106 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 111 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 107 | pub struct GtsIndication { | 112 | pub struct GtsIndication { |
| 108 | /// The short address of the device that has been allocated or deallocated a GTS | 113 | /// The short address of the device that has been allocated or deallocated a GTS |
| @@ -126,6 +131,7 @@ impl ParseableMacEvent for GtsIndication {} | |||
| 126 | /// MLME ORPHAN Indication which is used by the coordinator to notify the | 131 | /// MLME ORPHAN Indication which is used by the coordinator to notify the |
| 127 | /// application of the presence of an orphaned device | 132 | /// application of the presence of an orphaned device |
| 128 | #[repr(C)] | 133 | #[repr(C)] |
| 134 | #[derive(Debug)] | ||
| 129 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 135 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 130 | pub struct OrphanIndication { | 136 | pub struct OrphanIndication { |
| 131 | /// Extended address of the orphaned device | 137 | /// Extended address of the orphaned device |
| @@ -147,6 +153,7 @@ impl ParseableMacEvent for OrphanIndication {} | |||
| 147 | /// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss | 153 | /// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss |
| 148 | /// of synchronization with the coordinator | 154 | /// of synchronization with the coordinator |
| 149 | #[repr(C)] | 155 | #[repr(C)] |
| 156 | #[derive(Debug)] | ||
| 150 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 157 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 151 | pub struct SyncLossIndication { | 158 | pub struct SyncLossIndication { |
| 152 | /// The PAN identifier with which the device lost synchronization or to which it was realigned | 159 | /// The PAN identifier with which the device lost synchronization or to which it was realigned |
| @@ -172,6 +179,7 @@ impl ParseableMacEvent for SyncLossIndication {} | |||
| 172 | /// MLME DPS Indication which indicates the expiration of the DPSIndexDuration | 179 | /// MLME DPS Indication which indicates the expiration of the DPSIndexDuration |
| 173 | /// and the resetting of the DPS values in the PHY | 180 | /// and the resetting of the DPS values in the PHY |
| 174 | #[repr(C)] | 181 | #[repr(C)] |
| 182 | #[derive(Debug)] | ||
| 175 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 183 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 176 | pub struct DpsIndication { | 184 | pub struct DpsIndication { |
| 177 | /// byte stuffing to keep 32 bit alignment | 185 | /// byte stuffing to keep 32 bit alignment |
| @@ -181,6 +189,7 @@ pub struct DpsIndication { | |||
| 181 | impl ParseableMacEvent for DpsIndication {} | 189 | impl ParseableMacEvent for DpsIndication {} |
| 182 | 190 | ||
| 183 | #[repr(C)] | 191 | #[repr(C)] |
| 192 | #[derive(Debug)] | ||
| 184 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 193 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 185 | pub struct DataIndication { | 194 | pub struct DataIndication { |
| 186 | /// Pointer to the set of octets forming the MSDU being indicated | 195 | /// Pointer to the set of octets forming the MSDU being indicated |
| @@ -236,14 +245,15 @@ pub struct DataIndication { | |||
| 236 | impl ParseableMacEvent for DataIndication {} | 245 | impl ParseableMacEvent for DataIndication {} |
| 237 | 246 | ||
| 238 | impl DataIndication { | 247 | impl DataIndication { |
| 239 | pub fn payload<'a>(&'a self) -> &'a [u8] { | 248 | pub fn payload<'a>(&'a self) -> &'a mut [u8] { |
| 240 | unsafe { slice::from_raw_parts(self.msdu_ptr, self.msdu_length as usize) } | 249 | unsafe { slice::from_raw_parts_mut(self.msdu_ptr as *mut _, self.msdu_length as usize) } |
| 241 | } | 250 | } |
| 242 | } | 251 | } |
| 243 | 252 | ||
| 244 | /// MLME POLL Indication which will be used for indicating the Data Request | 253 | /// MLME POLL Indication which will be used for indicating the Data Request |
| 245 | /// reception to upper layer as defined in Zigbee r22 - D.8.2 | 254 | /// reception to upper layer as defined in Zigbee r22 - D.8.2 |
| 246 | #[repr(C)] | 255 | #[repr(C)] |
| 256 | #[derive(Debug)] | ||
| 247 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 257 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 248 | pub struct PollIndication { | 258 | pub struct PollIndication { |
| 249 | /// addressing mode used | 259 | /// addressing mode used |
diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs index 8d5edad6b..c847a5cca 100644 --- a/embassy-stm32-wpan/src/mac/mod.rs +++ b/embassy-stm32-wpan/src/mac/mod.rs | |||
| @@ -1,8 +1,21 @@ | |||
| 1 | pub mod commands; | 1 | pub mod commands; |
| 2 | mod consts; | 2 | mod consts; |
| 3 | pub mod control; | ||
| 4 | mod driver; | ||
| 3 | pub mod event; | 5 | pub mod event; |
| 4 | pub mod indications; | 6 | pub mod indications; |
| 5 | mod macros; | 7 | mod macros; |
| 6 | mod opcodes; | 8 | mod opcodes; |
| 7 | pub mod responses; | 9 | pub mod responses; |
| 10 | pub mod runner; | ||
| 8 | pub mod typedefs; | 11 | pub mod typedefs; |
| 12 | |||
| 13 | pub use crate::mac::control::Control; | ||
| 14 | use crate::mac::driver::Driver; | ||
| 15 | pub use crate::mac::runner::Runner; | ||
| 16 | |||
| 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/responses.rs b/embassy-stm32-wpan/src/mac/responses.rs index 5d203084c..544fdaae8 100644 --- a/embassy-stm32-wpan/src/mac/responses.rs +++ b/embassy-stm32-wpan/src/mac/responses.rs | |||
| @@ -8,6 +8,7 @@ use super::typedefs::{ | |||
| 8 | /// MLME ASSOCIATE Confirm used to inform of the initiating device whether | 8 | /// MLME ASSOCIATE Confirm used to inform of the initiating device whether |
| 9 | /// its request to associate was successful or unsuccessful | 9 | /// its request to associate was successful or unsuccessful |
| 10 | #[repr(C)] | 10 | #[repr(C)] |
| 11 | #[derive(Debug)] | ||
| 11 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 12 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 12 | pub struct AssociateConfirm { | 13 | pub struct AssociateConfirm { |
| 13 | /// short address allocated by the coordinator on successful association | 14 | /// short address allocated by the coordinator on successful association |
| @@ -30,6 +31,7 @@ impl ParseableMacEvent for AssociateConfirm {} | |||
| 30 | 31 | ||
| 31 | /// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application. | 32 | /// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application. |
| 32 | #[repr(C)] | 33 | #[repr(C)] |
| 34 | #[derive(Debug)] | ||
| 33 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 35 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 34 | pub struct DisassociateConfirm { | 36 | pub struct DisassociateConfirm { |
| 35 | /// status of the disassociation attempt | 37 | /// status of the disassociation attempt |
| @@ -46,6 +48,7 @@ impl ParseableMacEvent for DisassociateConfirm {} | |||
| 46 | 48 | ||
| 47 | /// MLME GET Confirm which requests information about a given PIB attribute | 49 | /// MLME GET Confirm which requests information about a given PIB attribute |
| 48 | #[repr(C)] | 50 | #[repr(C)] |
| 51 | #[derive(Debug)] | ||
| 49 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 52 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 50 | pub struct GetConfirm { | 53 | pub struct GetConfirm { |
| 51 | /// The pointer to the value of the PIB attribute attempted to read | 54 | /// The pointer to the value of the PIB attribute attempted to read |
| @@ -65,6 +68,7 @@ impl ParseableMacEvent for GetConfirm {} | |||
| 65 | /// MLME GTS Confirm which eports the results of a request to allocate a new GTS | 68 | /// MLME GTS Confirm which eports the results of a request to allocate a new GTS |
| 66 | /// or to deallocate an existing GTS | 69 | /// or to deallocate an existing GTS |
| 67 | #[repr(C)] | 70 | #[repr(C)] |
| 71 | #[derive(Debug)] | ||
| 68 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 72 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 69 | pub struct GtsConfirm { | 73 | pub struct GtsConfirm { |
| 70 | /// The characteristics of the GTS | 74 | /// The characteristics of the GTS |
| @@ -79,10 +83,11 @@ impl ParseableMacEvent for GtsConfirm {} | |||
| 79 | 83 | ||
| 80 | /// MLME RESET Confirm which is used to report the results of the reset operation | 84 | /// MLME RESET Confirm which is used to report the results of the reset operation |
| 81 | #[repr(C)] | 85 | #[repr(C)] |
| 86 | #[derive(Debug)] | ||
| 82 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 87 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 83 | pub struct ResetConfirm { | 88 | pub struct ResetConfirm { |
| 84 | /// The result of the reset operation | 89 | /// The result of the reset operation |
| 85 | status: MacStatus, | 90 | pub status: MacStatus, |
| 86 | /// byte stuffing to keep 32 bit alignment | 91 | /// byte stuffing to keep 32 bit alignment |
| 87 | a_stuffing: [u8; 3], | 92 | a_stuffing: [u8; 3], |
| 88 | } | 93 | } |
| @@ -92,10 +97,11 @@ impl ParseableMacEvent for ResetConfirm {} | |||
| 92 | /// MLME RX ENABLE Confirm which is used to report the results of the attempt | 97 | /// MLME RX ENABLE Confirm which is used to report the results of the attempt |
| 93 | /// to enable or disable the receiver | 98 | /// to enable or disable the receiver |
| 94 | #[repr(C)] | 99 | #[repr(C)] |
| 100 | #[derive(Debug)] | ||
| 95 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 101 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 96 | pub struct RxEnableConfirm { | 102 | pub struct RxEnableConfirm { |
| 97 | /// Result of the request to enable or disable the receiver | 103 | /// Result of the request to enable or disable the receiver |
| 98 | status: MacStatus, | 104 | pub status: MacStatus, |
| 99 | /// byte stuffing to keep 32 bit alignment | 105 | /// byte stuffing to keep 32 bit alignment |
| 100 | a_stuffing: [u8; 3], | 106 | a_stuffing: [u8; 3], |
| 101 | } | 107 | } |
| @@ -104,6 +110,7 @@ impl ParseableMacEvent for RxEnableConfirm {} | |||
| 104 | 110 | ||
| 105 | /// MLME SCAN Confirm which is used to report the result of the channel scan request | 111 | /// MLME SCAN Confirm which is used to report the result of the channel scan request |
| 106 | #[repr(C)] | 112 | #[repr(C)] |
| 113 | #[derive(Debug)] | ||
| 107 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 114 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 108 | pub struct ScanConfirm { | 115 | pub struct ScanConfirm { |
| 109 | /// Status of the scan request | 116 | /// Status of the scan request |
| @@ -130,6 +137,7 @@ impl ParseableMacEvent for ScanConfirm {} | |||
| 130 | 137 | ||
| 131 | /// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute | 138 | /// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute |
| 132 | #[repr(C)] | 139 | #[repr(C)] |
| 140 | #[derive(Debug)] | ||
| 133 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 141 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 134 | pub struct SetConfirm { | 142 | pub struct SetConfirm { |
| 135 | /// The result of the set operation | 143 | /// The result of the set operation |
| @@ -145,6 +153,7 @@ impl ParseableMacEvent for SetConfirm {} | |||
| 145 | /// MLME START Confirm which is used to report the results of the attempt to | 153 | /// MLME START Confirm which is used to report the results of the attempt to |
| 146 | /// start using a new superframe configuration | 154 | /// start using a new superframe configuration |
| 147 | #[repr(C)] | 155 | #[repr(C)] |
| 156 | #[derive(Debug)] | ||
| 148 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 157 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 149 | pub struct StartConfirm { | 158 | pub struct StartConfirm { |
| 150 | /// Result of the attempt to start using an updated superframe configuration | 159 | /// Result of the attempt to start using an updated superframe configuration |
| @@ -157,6 +166,7 @@ impl ParseableMacEvent for StartConfirm {} | |||
| 157 | 166 | ||
| 158 | /// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data | 167 | /// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data |
| 159 | #[repr(C)] | 168 | #[repr(C)] |
| 169 | #[derive(Debug)] | ||
| 160 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 170 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 161 | pub struct PollConfirm { | 171 | pub struct PollConfirm { |
| 162 | /// The status of the data request | 172 | /// The status of the data request |
| @@ -169,6 +179,7 @@ impl ParseableMacEvent for PollConfirm {} | |||
| 169 | 179 | ||
| 170 | /// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS | 180 | /// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS |
| 171 | #[repr(C)] | 181 | #[repr(C)] |
| 182 | #[derive(Debug)] | ||
| 172 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 183 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 173 | pub struct DpsConfirm { | 184 | pub struct DpsConfirm { |
| 174 | /// The status of the DPS request | 185 | /// The status of the DPS request |
| @@ -182,10 +193,11 @@ impl ParseableMacEvent for DpsConfirm {} | |||
| 182 | /// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide | 193 | /// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide |
| 183 | /// channel sounding information | 194 | /// channel sounding information |
| 184 | #[repr(C)] | 195 | #[repr(C)] |
| 196 | #[derive(Debug)] | ||
| 185 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 197 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 186 | pub struct SoundingConfirm { | 198 | pub struct SoundingConfirm { |
| 187 | /// Results of the sounding measurement | 199 | /// Results of the sounding measurement |
| 188 | sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED], | 200 | pub sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED], |
| 189 | 201 | ||
| 190 | status: u8, | 202 | status: u8, |
| 191 | } | 203 | } |
| @@ -195,6 +207,7 @@ impl ParseableMacEvent for SoundingConfirm {} | |||
| 195 | /// MLME CALIBRATE Confirm which reports the result of a request to the PHY | 207 | /// MLME CALIBRATE Confirm which reports the result of a request to the PHY |
| 196 | /// to provide internal propagation path information | 208 | /// to provide internal propagation path information |
| 197 | #[repr(C)] | 209 | #[repr(C)] |
| 210 | #[derive(Debug)] | ||
| 198 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 211 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 199 | pub struct CalibrateConfirm { | 212 | pub struct CalibrateConfirm { |
| 200 | /// The status of the attempt to return sounding data | 213 | /// The status of the attempt to return sounding data |
| @@ -214,6 +227,7 @@ impl ParseableMacEvent for CalibrateConfirm {} | |||
| 214 | /// MCPS DATA Confirm which will be used for reporting the results of | 227 | /// MCPS DATA Confirm which will be used for reporting the results of |
| 215 | /// MAC data related requests from the application | 228 | /// MAC data related requests from the application |
| 216 | #[repr(C)] | 229 | #[repr(C)] |
| 230 | #[derive(Debug)] | ||
| 217 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 231 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 218 | pub struct DataConfirm { | 232 | pub struct DataConfirm { |
| 219 | /// The handle associated with the MSDU being confirmed | 233 | /// The handle associated with the MSDU being confirmed |
| @@ -245,6 +259,7 @@ impl ParseableMacEvent for DataConfirm {} | |||
| 245 | /// MCPS PURGE Confirm which will be used by the MAC to notify the application of | 259 | /// MCPS PURGE Confirm which will be used by the MAC to notify the application of |
| 246 | /// the status of its request to purge an MSDU from the transaction queue | 260 | /// the status of its request to purge an MSDU from the transaction queue |
| 247 | #[repr(C)] | 261 | #[repr(C)] |
| 262 | #[derive(Debug)] | ||
| 248 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 263 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 249 | pub struct PurgeConfirm { | 264 | pub struct PurgeConfirm { |
| 250 | /// Handle associated with the MSDU requested to be purged from the transaction queue | 265 | /// Handle associated with the MSDU requested to be purged from the transaction queue |
diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs new file mode 100644 index 000000000..1be6df8a4 --- /dev/null +++ b/embassy-stm32-wpan/src/mac/runner.rs | |||
| @@ -0,0 +1,109 @@ | |||
| 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 | |||
| 10 | use crate::mac::commands::DataRequest; | ||
| 11 | use crate::mac::event::MacEvent; | ||
| 12 | use crate::mac::typedefs::{AddressMode, MacAddress, PanId, SecurityLevel}; | ||
| 13 | use crate::mac::MTU; | ||
| 14 | use crate::sub::mac::Mac; | ||
| 15 | |||
| 16 | type ZeroCopyPubSub<M, T> = blocking_mutex::Mutex<M, RefCell<Option<Signal<NoopRawMutex, T>>>>; | ||
| 17 | |||
| 18 | pub struct Runner<'a> { | ||
| 19 | pub(crate) mac_subsystem: Mac, | ||
| 20 | // rx event backpressure is already provided through the MacEvent drop mechanism | ||
| 21 | // therefore, we don't need to worry about overwriting events | ||
| 22 | pub(crate) rx_event_channel: ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>, | ||
| 23 | pub(crate) read_mutex: Mutex<CriticalSectionRawMutex, ()>, | ||
| 24 | pub(crate) write_mutex: Mutex<CriticalSectionRawMutex, ()>, | ||
| 25 | pub(crate) rx_channel: Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>, | ||
| 26 | pub(crate) tx_channel: Channel<CriticalSectionRawMutex, (&'a mut [u8; MTU], usize), 5>, | ||
| 27 | pub(crate) tx_buf_channel: Channel<CriticalSectionRawMutex, &'a mut [u8; MTU], 5>, | ||
| 28 | } | ||
| 29 | |||
| 30 | impl<'a> Runner<'a> { | ||
| 31 | pub fn new(mac: Mac, tx_buf_queue: [&'a mut [u8; MTU]; 5]) -> Self { | ||
| 32 | let this = Self { | ||
| 33 | mac_subsystem: mac, | ||
| 34 | rx_event_channel: blocking_mutex::Mutex::new(RefCell::new(None)), | ||
| 35 | read_mutex: Mutex::new(()), | ||
| 36 | write_mutex: Mutex::new(()), | ||
| 37 | rx_channel: Channel::new(), | ||
| 38 | tx_channel: Channel::new(), | ||
| 39 | tx_buf_channel: Channel::new(), | ||
| 40 | }; | ||
| 41 | |||
| 42 | for buf in tx_buf_queue { | ||
| 43 | this.tx_buf_channel.try_send(buf).unwrap(); | ||
| 44 | } | ||
| 45 | |||
| 46 | this | ||
| 47 | } | ||
| 48 | |||
| 49 | pub async fn run(&'a self) -> ! { | ||
| 50 | join::join( | ||
| 51 | async { | ||
| 52 | loop { | ||
| 53 | if let Ok(mac_event) = self.mac_subsystem.read().await { | ||
| 54 | match mac_event { | ||
| 55 | MacEvent::McpsDataInd(_) => { | ||
| 56 | self.rx_channel.send(mac_event).await; | ||
| 57 | } | ||
| 58 | _ => { | ||
| 59 | self.rx_event_channel.lock(|s| { | ||
| 60 | match &*s.borrow() { | ||
| 61 | Some(signal) => { | ||
| 62 | signal.signal(mac_event); | ||
| 63 | } | ||
| 64 | None => {} | ||
| 65 | }; | ||
| 66 | }); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | } | ||
| 70 | } | ||
| 71 | }, | ||
| 72 | async { | ||
| 73 | let mut msdu_handle = 0x02; | ||
| 74 | |||
| 75 | loop { | ||
| 76 | let (buf, len) = self.tx_channel.recv().await; | ||
| 77 | let _wm = self.write_mutex.lock().await; | ||
| 78 | |||
| 79 | // The mutex should be dropped on the next loop iteration | ||
| 80 | self.mac_subsystem | ||
| 81 | .send_command( | ||
| 82 | DataRequest { | ||
| 83 | src_addr_mode: AddressMode::Short, | ||
| 84 | dst_addr_mode: AddressMode::Short, | ||
| 85 | dst_pan_id: PanId([0x1A, 0xAA]), | ||
| 86 | dst_address: MacAddress::BROADCAST, | ||
| 87 | msdu_handle: msdu_handle, | ||
| 88 | ack_tx: 0x00, | ||
| 89 | gts_tx: false, | ||
| 90 | security_level: SecurityLevel::Unsecure, | ||
| 91 | ..Default::default() | ||
| 92 | } | ||
| 93 | .set_buffer(&buf[..len]), | ||
| 94 | ) | ||
| 95 | .await | ||
| 96 | .unwrap(); | ||
| 97 | |||
| 98 | msdu_handle = msdu_handle.wrapping_add(1); | ||
| 99 | |||
| 100 | // The tx channel should always be of equal capacity to the tx_buf channel | ||
| 101 | self.tx_buf_channel.try_send(buf).unwrap(); | ||
| 102 | } | ||
| 103 | }, | ||
| 104 | ) | ||
| 105 | .await; | ||
| 106 | |||
| 107 | loop {} | ||
| 108 | } | ||
| 109 | } | ||
diff --git a/embassy-stm32-wpan/src/mac/typedefs.rs b/embassy-stm32-wpan/src/mac/typedefs.rs index 98c67c86b..0552b8ea1 100644 --- a/embassy-stm32-wpan/src/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/mac/typedefs.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | use core::fmt::Debug; | ||
| 2 | |||
| 1 | use crate::numeric_enum; | 3 | use crate::numeric_enum; |
| 2 | 4 | ||
| 3 | #[derive(Debug)] | 5 | #[derive(Debug)] |
| @@ -37,7 +39,7 @@ numeric_enum! { | |||
| 37 | numeric_enum! { | 39 | numeric_enum! { |
| 38 | #[repr(u8)] | 40 | #[repr(u8)] |
| 39 | /// this enum contains all the MAC PIB Ids | 41 | /// this enum contains all the MAC PIB Ids |
| 40 | #[derive(Default)] | 42 | #[derive(Default, Debug)] |
| 41 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 43 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 42 | pub enum PibId { | 44 | pub enum PibId { |
| 43 | // PHY | 45 | // PHY |
| @@ -96,7 +98,7 @@ numeric_enum! { | |||
| 96 | 98 | ||
| 97 | numeric_enum! { | 99 | numeric_enum! { |
| 98 | #[repr(u8)] | 100 | #[repr(u8)] |
| 99 | #[derive(Default, Clone, Copy)] | 101 | #[derive(Default, Clone, Copy, Debug)] |
| 100 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 102 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 101 | pub enum AddressMode { | 103 | pub enum AddressMode { |
| 102 | #[default] | 104 | #[default] |
| @@ -113,6 +115,18 @@ pub union MacAddress { | |||
| 113 | pub extended: [u8; 8], | 115 | pub extended: [u8; 8], |
| 114 | } | 116 | } |
| 115 | 117 | ||
| 118 | impl Debug for MacAddress { | ||
| 119 | fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | ||
| 120 | unsafe { | ||
| 121 | write!( | ||
| 122 | fmt, | ||
| 123 | "MacAddress {{ short: {:?}, extended: {:?} }}", | ||
| 124 | self.short, self.extended | ||
| 125 | ) | ||
| 126 | } | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 116 | #[cfg(feature = "defmt")] | 130 | #[cfg(feature = "defmt")] |
| 117 | impl defmt::Format for MacAddress { | 131 | impl defmt::Format for MacAddress { |
| 118 | fn format(&self, fmt: defmt::Formatter) { | 132 | fn format(&self, fmt: defmt::Formatter) { |
| @@ -159,7 +173,7 @@ pub struct GtsCharacteristics { | |||
| 159 | 173 | ||
| 160 | /// MAC PAN Descriptor which contains the network details of the device from | 174 | /// MAC PAN Descriptor which contains the network details of the device from |
| 161 | /// which the beacon is received | 175 | /// which the beacon is received |
| 162 | #[derive(Default, Clone, Copy)] | 176 | #[derive(Default, Clone, Copy, Debug)] |
| 163 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 177 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 164 | pub struct PanDescriptor { | 178 | pub struct PanDescriptor { |
| 165 | /// PAN identifier of the coordinator | 179 | /// PAN identifier of the coordinator |
| @@ -223,7 +237,7 @@ impl TryFrom<&[u8]> for PanDescriptor { | |||
| 223 | 237 | ||
| 224 | numeric_enum! { | 238 | numeric_enum! { |
| 225 | #[repr(u8)] | 239 | #[repr(u8)] |
| 226 | #[derive(Default, Clone, Copy)] | 240 | #[derive(Default, Clone, Copy, Debug)] |
| 227 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 241 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 228 | /// Building wireless applications with STM32WB series MCUs - Application note 13.10.3 | 242 | /// Building wireless applications with STM32WB series MCUs - Application note 13.10.3 |
| 229 | pub enum MacChannel { | 243 | pub enum MacChannel { |
| @@ -289,7 +303,7 @@ defmt::bitflags! { | |||
| 289 | 303 | ||
| 290 | numeric_enum! { | 304 | numeric_enum! { |
| 291 | #[repr(u8)] | 305 | #[repr(u8)] |
| 292 | #[derive(Default, Clone, Copy)] | 306 | #[derive(Default, Clone, Copy, Debug)] |
| 293 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 307 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 294 | pub enum KeyIdMode { | 308 | pub enum KeyIdMode { |
| 295 | #[default] | 309 | #[default] |
| @@ -306,6 +320,7 @@ numeric_enum! { | |||
| 306 | 320 | ||
| 307 | numeric_enum! { | 321 | numeric_enum! { |
| 308 | #[repr(u8)] | 322 | #[repr(u8)] |
| 323 | #[derive(Debug)] | ||
| 309 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 324 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 310 | pub enum AssociationStatus { | 325 | pub enum AssociationStatus { |
| 311 | /// Association successful | 326 | /// Association successful |
| @@ -319,7 +334,7 @@ numeric_enum! { | |||
| 319 | 334 | ||
| 320 | numeric_enum! { | 335 | numeric_enum! { |
| 321 | #[repr(u8)] | 336 | #[repr(u8)] |
| 322 | #[derive(Clone, Copy)] | 337 | #[derive(Clone, Copy, Debug)] |
| 323 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 338 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 324 | pub enum DisassociationReason { | 339 | pub enum DisassociationReason { |
| 325 | /// The coordinator wishes the device to leave the PAN. | 340 | /// The coordinator wishes the device to leave the PAN. |
| @@ -331,7 +346,7 @@ numeric_enum! { | |||
| 331 | 346 | ||
| 332 | numeric_enum! { | 347 | numeric_enum! { |
| 333 | #[repr(u8)] | 348 | #[repr(u8)] |
| 334 | #[derive(Default, Clone, Copy)] | 349 | #[derive(Default, Clone, Copy, Debug)] |
| 335 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 350 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 336 | pub enum SecurityLevel { | 351 | pub enum SecurityLevel { |
| 337 | /// MAC Unsecured Mode Security | 352 | /// MAC Unsecured Mode Security |
| @@ -346,6 +361,7 @@ numeric_enum! { | |||
| 346 | 361 | ||
| 347 | numeric_enum! { | 362 | numeric_enum! { |
| 348 | #[repr(u8)] | 363 | #[repr(u8)] |
| 364 | #[derive(Debug)] | ||
| 349 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 365 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 350 | pub enum ScanType { | 366 | pub enum ScanType { |
| 351 | EdScan = 0x00, | 367 | EdScan = 0x00, |
| @@ -356,7 +372,7 @@ numeric_enum! { | |||
| 356 | } | 372 | } |
| 357 | 373 | ||
| 358 | /// newtype for Pan Id | 374 | /// newtype for Pan Id |
| 359 | #[derive(Default, Clone, Copy)] | 375 | #[derive(Default, Clone, Copy, Debug)] |
| 360 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 376 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 361 | pub struct PanId(pub [u8; 2]); | 377 | pub struct PanId(pub [u8; 2]); |
| 362 | 378 | ||
diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs index d9bf4c909..b0cf0248a 100644 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ b/embassy-stm32-wpan/src/sub/mac.rs | |||
| @@ -12,7 +12,7 @@ use crate::cmd::CmdPacket; | |||
| 12 | use crate::consts::TlPacketType; | 12 | use crate::consts::TlPacketType; |
| 13 | use crate::evt::{EvtBox, EvtPacket}; | 13 | use crate::evt::{EvtBox, EvtPacket}; |
| 14 | use crate::mac::commands::MacCommand; | 14 | use crate::mac::commands::MacCommand; |
| 15 | use crate::mac::event::Event; | 15 | use crate::mac::event::MacEvent; |
| 16 | use crate::mac::typedefs::MacError; | 16 | use crate::mac::typedefs::MacError; |
| 17 | use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; | 17 | use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; |
| 18 | use crate::{channels, evt}; | 18 | use crate::{channels, evt}; |
| @@ -94,14 +94,16 @@ impl Mac { | |||
| 94 | } | 94 | } |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | pub async fn read(&self) -> Event { | 97 | pub async fn read(&self) -> Result<MacEvent<'_>, ()> { |
| 98 | Event::new(self.tl_read().await) | 98 | MacEvent::new(self.tl_read().await) |
| 99 | } | 99 | } |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | impl evt::MemoryManager for Mac { | 102 | impl evt::MemoryManager for Mac { |
| 103 | /// SAFETY: passing a pointer to something other than a managed event packet is UB | 103 | /// SAFETY: passing a pointer to something other than a managed event packet is UB |
| 104 | unsafe fn drop_event_packet(_: *mut EvtPacket) { | 104 | unsafe fn drop_event_packet(_: *mut EvtPacket) { |
| 105 | trace!("mac drop event"); | ||
| 106 | |||
| 105 | // Write the ack | 107 | // Write the ack |
| 106 | CmdPacket::write_into( | 108 | CmdPacket::write_into( |
| 107 | MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _, | 109 | MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _, |
| @@ -111,7 +113,7 @@ impl evt::MemoryManager for Mac { | |||
| 111 | ); | 113 | ); |
| 112 | 114 | ||
| 113 | // Clear the rx flag | 115 | // Clear the rx flag |
| 114 | let _ = poll_once(Ipcc::receive::<bool>( | 116 | let _ = poll_once(Ipcc::receive::<()>( |
| 115 | channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, | 117 | channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, |
| 116 | || None, | 118 | || None, |
| 117 | )); | 119 | )); |
diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs index 77352874d..f421af392 100644 --- a/embassy-sync/src/channel.rs +++ b/embassy-sync/src/channel.rs | |||
| @@ -335,6 +335,12 @@ impl<T, const N: usize> ChannelState<T, N> { | |||
| 335 | } | 335 | } |
| 336 | } | 336 | } |
| 337 | 337 | ||
| 338 | fn poll_ready_to_receive(&mut self, cx: &mut Context<'_>) -> bool { | ||
| 339 | self.receiver_waker.register(cx.waker()); | ||
| 340 | |||
| 341 | !self.queue.is_empty() | ||
| 342 | } | ||
| 343 | |||
| 338 | fn try_send(&mut self, message: T) -> Result<(), TrySendError<T>> { | 344 | fn try_send(&mut self, message: T) -> Result<(), TrySendError<T>> { |
| 339 | self.try_send_with_context(message, None) | 345 | self.try_send_with_context(message, None) |
| 340 | } | 346 | } |
| @@ -353,6 +359,12 @@ impl<T, const N: usize> ChannelState<T, N> { | |||
| 353 | } | 359 | } |
| 354 | } | 360 | } |
| 355 | } | 361 | } |
| 362 | |||
| 363 | fn poll_ready_to_send(&mut self, cx: &mut Context<'_>) -> bool { | ||
| 364 | self.senders_waker.register(cx.waker()); | ||
| 365 | |||
| 366 | !self.queue.is_full() | ||
| 367 | } | ||
| 356 | } | 368 | } |
| 357 | 369 | ||
| 358 | /// A bounded channel for communicating between asynchronous tasks | 370 | /// A bounded channel for communicating between asynchronous tasks |
| @@ -401,6 +413,16 @@ where | |||
| 401 | self.lock(|c| c.try_send_with_context(m, cx)) | 413 | self.lock(|c| c.try_send_with_context(m, cx)) |
| 402 | } | 414 | } |
| 403 | 415 | ||
| 416 | /// Allows a poll_fn to poll until the channel is ready to receive | ||
| 417 | pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool { | ||
| 418 | self.lock(|c| c.poll_ready_to_receive(cx)) | ||
| 419 | } | ||
| 420 | |||
| 421 | /// Allows a poll_fn to poll until the channel is ready to send | ||
| 422 | pub fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> bool { | ||
| 423 | self.lock(|c| c.poll_ready_to_send(cx)) | ||
| 424 | } | ||
| 425 | |||
| 404 | /// Get a sender for this channel. | 426 | /// Get a sender for this channel. |
| 405 | pub fn sender(&self) -> Sender<'_, M, T, N> { | 427 | pub fn sender(&self) -> Sender<'_, M, T, N> { |
| 406 | Sender { channel: self } | 428 | Sender { channel: self } |
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index becf2d3fb..7c0b83e65 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml | |||
| @@ -10,6 +10,7 @@ embassy-executor = { version = "0.2.0", path = "../../embassy-executor", feature | |||
| 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } |
| 12 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } | 12 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } |
| 13 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ieee802154", "nightly"], optional=true } | ||
| 13 | 14 | ||
| 14 | defmt = "0.3" | 15 | defmt = "0.3" |
| 15 | defmt-rtt = "0.4" | 16 | defmt-rtt = "0.4" |
| @@ -20,11 +21,11 @@ embedded-hal = "0.2.6" | |||
| 20 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 21 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
| 21 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 22 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
| 22 | heapless = { version = "0.7.5", default-features = false } | 23 | heapless = { version = "0.7.5", default-features = false } |
| 23 | 24 | static_cell = { version = "1.1", features = ["nightly"]} | |
| 24 | 25 | ||
| 25 | [features] | 26 | [features] |
| 26 | default = ["ble", "mac"] | 27 | default = ["ble", "mac"] |
| 27 | mac = ["embassy-stm32-wpan/mac"] | 28 | mac = ["embassy-stm32-wpan/mac", "dep:embassy-net"] |
| 28 | ble = ["embassy-stm32-wpan/ble"] | 29 | ble = ["embassy-stm32-wpan/ble"] |
| 29 | 30 | ||
| 30 | [[bin]] | 31 | [[bin]] |
| @@ -40,6 +41,10 @@ name = "mac_ffd" | |||
| 40 | required-features = ["mac"] | 41 | required-features = ["mac"] |
| 41 | 42 | ||
| 42 | [[bin]] | 43 | [[bin]] |
| 44 | name = "mac_ffd_net" | ||
| 45 | required-features = ["mac"] | ||
| 46 | |||
| 47 | [[bin]] | ||
| 43 | name = "eddystone_beacon" | 48 | name = "eddystone_beacon" |
| 44 | required-features = ["ble"] | 49 | required-features = ["ble"] |
| 45 | 50 | ||
diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index bc71e29aa..1379ac6ba 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs | |||
| @@ -73,10 +73,7 @@ async fn main(spawner: Spawner) { | |||
| 73 | }) | 73 | }) |
| 74 | .await | 74 | .await |
| 75 | .unwrap(); | 75 | .unwrap(); |
| 76 | { | 76 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); |
| 77 | let evt = mbox.mac_subsystem.read().await; | ||
| 78 | defmt::info!("{:#x}", evt.mac_event()); | ||
| 79 | } | ||
| 80 | 77 | ||
| 81 | info!("setting extended address"); | 78 | info!("setting extended address"); |
| 82 | let extended_address: u64 = 0xACDE480000000001; | 79 | let extended_address: u64 = 0xACDE480000000001; |
| @@ -87,10 +84,7 @@ async fn main(spawner: Spawner) { | |||
| 87 | }) | 84 | }) |
| 88 | .await | 85 | .await |
| 89 | .unwrap(); | 86 | .unwrap(); |
| 90 | { | 87 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); |
| 91 | let evt = mbox.mac_subsystem.read().await; | ||
| 92 | defmt::info!("{:#x}", evt.mac_event()); | ||
| 93 | } | ||
| 94 | 88 | ||
| 95 | info!("setting short address"); | 89 | info!("setting short address"); |
| 96 | let short_address: u16 = 0x1122; | 90 | let short_address: u16 = 0x1122; |
| @@ -101,10 +95,7 @@ async fn main(spawner: Spawner) { | |||
| 101 | }) | 95 | }) |
| 102 | .await | 96 | .await |
| 103 | .unwrap(); | 97 | .unwrap(); |
| 104 | { | 98 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); |
| 105 | let evt = mbox.mac_subsystem.read().await; | ||
| 106 | defmt::info!("{:#x}", evt.mac_event()); | ||
| 107 | } | ||
| 108 | 99 | ||
| 109 | info!("setting association permit"); | 100 | info!("setting association permit"); |
| 110 | let association_permit: bool = true; | 101 | let association_permit: bool = true; |
| @@ -115,10 +106,7 @@ async fn main(spawner: Spawner) { | |||
| 115 | }) | 106 | }) |
| 116 | .await | 107 | .await |
| 117 | .unwrap(); | 108 | .unwrap(); |
| 118 | { | 109 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); |
| 119 | let evt = mbox.mac_subsystem.read().await; | ||
| 120 | defmt::info!("{:#x}", evt.mac_event()); | ||
| 121 | } | ||
| 122 | 110 | ||
| 123 | info!("setting TX power"); | 111 | info!("setting TX power"); |
| 124 | let transmit_power: i8 = 2; | 112 | let transmit_power: i8 = 2; |
| @@ -129,10 +117,7 @@ async fn main(spawner: Spawner) { | |||
| 129 | }) | 117 | }) |
| 130 | .await | 118 | .await |
| 131 | .unwrap(); | 119 | .unwrap(); |
| 132 | { | 120 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); |
| 133 | let evt = mbox.mac_subsystem.read().await; | ||
| 134 | defmt::info!("{:#x}", evt.mac_event()); | ||
| 135 | } | ||
| 136 | 121 | ||
| 137 | info!("starting FFD device"); | 122 | info!("starting FFD device"); |
| 138 | mbox.mac_subsystem | 123 | mbox.mac_subsystem |
| @@ -147,10 +132,7 @@ async fn main(spawner: Spawner) { | |||
| 147 | }) | 132 | }) |
| 148 | .await | 133 | .await |
| 149 | .unwrap(); | 134 | .unwrap(); |
| 150 | { | 135 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); |
| 151 | let evt = mbox.mac_subsystem.read().await; | ||
| 152 | defmt::info!("{:#x}", evt.mac_event()); | ||
| 153 | } | ||
| 154 | 136 | ||
| 155 | info!("setting RX on when idle"); | 137 | info!("setting RX on when idle"); |
| 156 | let rx_on_while_idle: bool = true; | 138 | let rx_on_while_idle: bool = true; |
| @@ -161,14 +143,11 @@ async fn main(spawner: Spawner) { | |||
| 161 | }) | 143 | }) |
| 162 | .await | 144 | .await |
| 163 | .unwrap(); | 145 | .unwrap(); |
| 164 | { | 146 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); |
| 165 | let evt = mbox.mac_subsystem.read().await; | ||
| 166 | defmt::info!("{:#x}", evt.mac_event()); | ||
| 167 | } | ||
| 168 | 147 | ||
| 169 | loop { | 148 | loop { |
| 170 | let evt = mbox.mac_subsystem.read().await; | 149 | let evt = mbox.mac_subsystem.read().await; |
| 171 | if let Ok(evt) = evt.mac_event() { | 150 | if let Ok(evt) = evt { |
| 172 | defmt::info!("parsed mac event"); | 151 | defmt::info!("parsed mac event"); |
| 173 | defmt::info!("{:#x}", evt); | 152 | defmt::info!("{:#x}", evt); |
| 174 | 153 | ||
diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs new file mode 100644 index 000000000..bbcd0a70f --- /dev/null +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs | |||
| @@ -0,0 +1,170 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use defmt::*; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_stm32::bind_interrupts; | ||
| 8 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | ||
| 9 | use embassy_stm32_wpan::mac::commands::{ResetRequest, SetRequest, StartRequest}; | ||
| 10 | use embassy_stm32_wpan::mac::typedefs::{MacChannel, PanId, PibId}; | ||
| 11 | use embassy_stm32_wpan::mac::{self, Runner}; | ||
| 12 | use embassy_stm32_wpan::sub::mm; | ||
| 13 | use embassy_stm32_wpan::TlMbox; | ||
| 14 | use static_cell::make_static; | ||
| 15 | use {defmt_rtt as _, panic_probe as _}; | ||
| 16 | |||
| 17 | bind_interrupts!(struct Irqs{ | ||
| 18 | IPCC_C1_RX => ReceiveInterruptHandler; | ||
| 19 | IPCC_C1_TX => TransmitInterruptHandler; | ||
| 20 | }); | ||
| 21 | |||
| 22 | #[embassy_executor::task] | ||
| 23 | async fn run_mm_queue(memory_manager: mm::MemoryManager) { | ||
| 24 | memory_manager.run_queue().await; | ||
| 25 | } | ||
| 26 | |||
| 27 | #[embassy_executor::task] | ||
| 28 | async fn run_mac(runner: &'static Runner<'static>) { | ||
| 29 | runner.run().await; | ||
| 30 | } | ||
| 31 | |||
| 32 | #[embassy_executor::main] | ||
| 33 | async fn main(spawner: Spawner) { | ||
| 34 | /* | ||
| 35 | How to make this work: | ||
| 36 | |||
| 37 | - Obtain a NUCLEO-STM32WB55 from your preferred supplier. | ||
| 38 | - Download and Install STM32CubeProgrammer. | ||
| 39 | - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from | ||
| 40 | gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x | ||
| 41 | - Open STM32CubeProgrammer | ||
| 42 | - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. | ||
| 43 | - Once complete, click connect to connect to the device. | ||
| 44 | - On the left hand pane, click the RSS signal icon to open "Firmware Upgrade Services". | ||
| 45 | - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file | ||
| 46 | - Select that file, the memory address, "verify download", and then "Firmware Upgrade". | ||
| 47 | - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the | ||
| 48 | stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. | ||
| 49 | - Select that file, the memory address, "verify download", and then "Firmware Upgrade". | ||
| 50 | - Select "Start Wireless Stack". | ||
| 51 | - Disconnect from the device. | ||
| 52 | - In the examples folder for stm32wb, modify the memory.x file to match your target device. | ||
| 53 | - Run this example. | ||
| 54 | |||
| 55 | Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. | ||
| 56 | */ | ||
| 57 | |||
| 58 | let p = embassy_stm32::init(Default::default()); | ||
| 59 | info!("Hello World!"); | ||
| 60 | |||
| 61 | let config = Config::default(); | ||
| 62 | let mbox = TlMbox::init(p.IPCC, Irqs, config); | ||
| 63 | |||
| 64 | spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); | ||
| 65 | |||
| 66 | let sys_event = mbox.sys_subsystem.read().await; | ||
| 67 | info!("sys event: {}", sys_event.payload()); | ||
| 68 | |||
| 69 | core::mem::drop(sys_event); | ||
| 70 | |||
| 71 | let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; | ||
| 72 | info!("initialized mac: {}", result); | ||
| 73 | |||
| 74 | info!("resetting"); | ||
| 75 | mbox.mac_subsystem | ||
| 76 | .send_command(&ResetRequest { | ||
| 77 | set_default_pib: true, | ||
| 78 | ..Default::default() | ||
| 79 | }) | ||
| 80 | .await | ||
| 81 | .unwrap(); | ||
| 82 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 83 | |||
| 84 | info!("setting extended address"); | ||
| 85 | let extended_address: u64 = 0xACDE480000000001; | ||
| 86 | mbox.mac_subsystem | ||
| 87 | .send_command(&SetRequest { | ||
| 88 | pib_attribute_ptr: &extended_address as *const _ as *const u8, | ||
| 89 | pib_attribute: PibId::ExtendedAddress, | ||
| 90 | }) | ||
| 91 | .await | ||
| 92 | .unwrap(); | ||
| 93 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 94 | |||
| 95 | info!("setting short address"); | ||
| 96 | let short_address: u16 = 0x1122; | ||
| 97 | mbox.mac_subsystem | ||
| 98 | .send_command(&SetRequest { | ||
| 99 | pib_attribute_ptr: &short_address as *const _ as *const u8, | ||
| 100 | pib_attribute: PibId::ShortAddress, | ||
| 101 | }) | ||
| 102 | .await | ||
| 103 | .unwrap(); | ||
| 104 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 105 | |||
| 106 | info!("setting association permit"); | ||
| 107 | let association_permit: bool = true; | ||
| 108 | mbox.mac_subsystem | ||
| 109 | .send_command(&SetRequest { | ||
| 110 | pib_attribute_ptr: &association_permit as *const _ as *const u8, | ||
| 111 | pib_attribute: PibId::AssociationPermit, | ||
| 112 | }) | ||
| 113 | .await | ||
| 114 | .unwrap(); | ||
| 115 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 116 | |||
| 117 | info!("setting TX power"); | ||
| 118 | let transmit_power: i8 = 2; | ||
| 119 | mbox.mac_subsystem | ||
| 120 | .send_command(&SetRequest { | ||
| 121 | pib_attribute_ptr: &transmit_power as *const _ as *const u8, | ||
| 122 | pib_attribute: PibId::TransmitPower, | ||
| 123 | }) | ||
| 124 | .await | ||
| 125 | .unwrap(); | ||
| 126 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 127 | |||
| 128 | info!("starting FFD device"); | ||
| 129 | mbox.mac_subsystem | ||
| 130 | .send_command(&StartRequest { | ||
| 131 | pan_id: PanId([0x1A, 0xAA]), | ||
| 132 | channel_number: MacChannel::Channel16, | ||
| 133 | beacon_order: 0x0F, | ||
| 134 | superframe_order: 0x0F, | ||
| 135 | pan_coordinator: true, | ||
| 136 | battery_life_extension: false, | ||
| 137 | ..Default::default() | ||
| 138 | }) | ||
| 139 | .await | ||
| 140 | .unwrap(); | ||
| 141 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 142 | |||
| 143 | info!("setting RX on when idle"); | ||
| 144 | let rx_on_while_idle: bool = true; | ||
| 145 | mbox.mac_subsystem | ||
| 146 | .send_command(&SetRequest { | ||
| 147 | pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, | ||
| 148 | pib_attribute: PibId::RxOnWhenIdle, | ||
| 149 | }) | ||
| 150 | .await | ||
| 151 | .unwrap(); | ||
| 152 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); | ||
| 153 | |||
| 154 | let tx_queue = [ | ||
| 155 | make_static!([0u8; 127]), | ||
| 156 | make_static!([0u8; 127]), | ||
| 157 | make_static!([0u8; 127]), | ||
| 158 | make_static!([0u8; 127]), | ||
| 159 | make_static!([0u8; 127]), | ||
| 160 | ]; | ||
| 161 | |||
| 162 | let runner = make_static!(Runner::new(mbox.mac_subsystem, tx_queue)); | ||
| 163 | |||
| 164 | spawner.spawn(run_mac(runner)).unwrap(); | ||
| 165 | |||
| 166 | let (driver, control) = mac::new(runner).await; | ||
| 167 | |||
| 168 | let _ = driver; | ||
| 169 | let _ = control; | ||
| 170 | } | ||
diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index 7cb401d89..4d8b6601a 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs | |||
| @@ -75,10 +75,7 @@ async fn main(spawner: Spawner) { | |||
| 75 | }) | 75 | }) |
| 76 | .await | 76 | .await |
| 77 | .unwrap(); | 77 | .unwrap(); |
| 78 | { | 78 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); |
| 79 | let evt = mbox.mac_subsystem.read().await; | ||
| 80 | defmt::info!("{:#x}", evt.mac_event()); | ||
| 81 | } | ||
| 82 | 79 | ||
| 83 | info!("setting extended address"); | 80 | info!("setting extended address"); |
| 84 | let extended_address: u64 = 0xACDE480000000002; | 81 | let extended_address: u64 = 0xACDE480000000002; |
| @@ -89,10 +86,7 @@ async fn main(spawner: Spawner) { | |||
| 89 | }) | 86 | }) |
| 90 | .await | 87 | .await |
| 91 | .unwrap(); | 88 | .unwrap(); |
| 92 | { | 89 | defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); |
| 93 | let evt = mbox.mac_subsystem.read().await; | ||
| 94 | defmt::info!("{:#x}", evt.mac_event()); | ||
| 95 | } | ||
| 96 | 90 | ||
| 97 | info!("getting extended address"); | 91 | info!("getting extended address"); |
| 98 | mbox.mac_subsystem | 92 | mbox.mac_subsystem |
| @@ -104,10 +98,10 @@ async fn main(spawner: Spawner) { | |||
| 104 | .unwrap(); | 98 | .unwrap(); |
| 105 | 99 | ||
| 106 | { | 100 | { |
| 107 | let evt = mbox.mac_subsystem.read().await; | 101 | let evt = mbox.mac_subsystem.read().await.unwrap(); |
| 108 | info!("{:#x}", evt.mac_event()); | 102 | info!("{:#x}", evt); |
| 109 | 103 | ||
| 110 | if let Ok(MacEvent::MlmeGetCnf(evt)) = evt.mac_event() { | 104 | if let MacEvent::MlmeGetCnf(evt) = evt { |
| 111 | if evt.pib_attribute_value_len == 8 { | 105 | if evt.pib_attribute_value_len == 8 { |
| 112 | let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; | 106 | let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; |
| 113 | 107 | ||
| @@ -132,10 +126,10 @@ async fn main(spawner: Spawner) { | |||
| 132 | info!("{}", a); | 126 | info!("{}", a); |
| 133 | mbox.mac_subsystem.send_command(&a).await.unwrap(); | 127 | mbox.mac_subsystem.send_command(&a).await.unwrap(); |
| 134 | let short_addr = { | 128 | let short_addr = { |
| 135 | let evt = mbox.mac_subsystem.read().await; | 129 | let evt = mbox.mac_subsystem.read().await.unwrap(); |
| 136 | info!("{:#x}", evt.mac_event()); | 130 | info!("{:#x}", evt); |
| 137 | 131 | ||
| 138 | if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt.mac_event() { | 132 | if let MacEvent::MlmeAssociateCnf(conf) = evt { |
| 139 | conf.assoc_short_address | 133 | conf.assoc_short_address |
| 140 | } else { | 134 | } else { |
| 141 | defmt::panic!() | 135 | defmt::panic!() |
| @@ -151,8 +145,8 @@ async fn main(spawner: Spawner) { | |||
| 151 | .await | 145 | .await |
| 152 | .unwrap(); | 146 | .unwrap(); |
| 153 | { | 147 | { |
| 154 | let evt = mbox.mac_subsystem.read().await; | 148 | let evt = mbox.mac_subsystem.read().await.unwrap(); |
| 155 | info!("{:#x}", evt.mac_event()); | 149 | info!("{:#x}", evt); |
| 156 | } | 150 | } |
| 157 | 151 | ||
| 158 | info!("sending data"); | 152 | info!("sending data"); |
| @@ -175,12 +169,14 @@ async fn main(spawner: Spawner) { | |||
| 175 | .await | 169 | .await |
| 176 | .unwrap(); | 170 | .unwrap(); |
| 177 | { | 171 | { |
| 178 | let evt = mbox.mac_subsystem.read().await; | 172 | let evt = mbox.mac_subsystem.read().await.unwrap(); |
| 179 | info!("{:#x}", evt.mac_event()); | 173 | info!("{:#x}", evt); |
| 180 | } | 174 | } |
| 181 | 175 | ||
| 182 | loop { | 176 | loop { |
| 183 | let evt = mbox.mac_subsystem.read().await; | 177 | match mbox.mac_subsystem.read().await { |
| 184 | info!("{:#x}", evt.mac_event()); | 178 | Ok(evt) => info!("{:#x}", evt), |
| 179 | _ => continue, | ||
| 180 | }; | ||
| 185 | } | 181 | } |
| 186 | } | 182 | } |
diff --git a/tests/stm32/src/bin/wpan_mac.rs b/tests/stm32/src/bin/wpan_mac.rs index d64a5ef81..b04a19ee9 100644 --- a/tests/stm32/src/bin/wpan_mac.rs +++ b/tests/stm32/src/bin/wpan_mac.rs | |||
| @@ -56,8 +56,8 @@ async fn main(spawner: Spawner) { | |||
| 56 | .await | 56 | .await |
| 57 | .unwrap(); | 57 | .unwrap(); |
| 58 | { | 58 | { |
| 59 | let evt = mbox.mac_subsystem.read().await; | 59 | let evt = mbox.mac_subsystem.read().await.unwrap(); |
| 60 | info!("{:#x}", evt.mac_event()); | 60 | info!("{:#x}", evt); |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | info!("setting extended address"); | 63 | info!("setting extended address"); |
| @@ -70,8 +70,8 @@ async fn main(spawner: Spawner) { | |||
| 70 | .await | 70 | .await |
| 71 | .unwrap(); | 71 | .unwrap(); |
| 72 | { | 72 | { |
| 73 | let evt = mbox.mac_subsystem.read().await; | 73 | let evt = mbox.mac_subsystem.read().await.unwrap(); |
| 74 | info!("{:#x}", evt.mac_event()); | 74 | info!("{:#x}", evt); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | info!("getting extended address"); | 77 | info!("getting extended address"); |
| @@ -82,11 +82,12 @@ async fn main(spawner: Spawner) { | |||
| 82 | }) | 82 | }) |
| 83 | .await | 83 | .await |
| 84 | .unwrap(); | 84 | .unwrap(); |
| 85 | |||
| 85 | { | 86 | { |
| 86 | let evt = mbox.mac_subsystem.read().await; | 87 | let evt = mbox.mac_subsystem.read().await.unwrap(); |
| 87 | info!("{:#x}", evt.mac_event()); | 88 | info!("{:#x}", evt); |
| 88 | 89 | ||
| 89 | if let Ok(MacEvent::MlmeGetCnf(evt)) = evt.mac_event() { | 90 | if let MacEvent::MlmeGetCnf(evt) = evt { |
| 90 | if evt.pib_attribute_value_len == 8 { | 91 | if evt.pib_attribute_value_len == 8 { |
| 91 | let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; | 92 | let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) }; |
| 92 | 93 | ||
| @@ -110,10 +111,13 @@ async fn main(spawner: Spawner) { | |||
| 110 | }; | 111 | }; |
| 111 | info!("{}", a); | 112 | info!("{}", a); |
| 112 | mbox.mac_subsystem.send_command(&a).await.unwrap(); | 113 | mbox.mac_subsystem.send_command(&a).await.unwrap(); |
| 113 | { | 114 | let short_addr = if let MacEvent::MlmeAssociateCnf(conf) = mbox.mac_subsystem.read().await.unwrap() { |
| 114 | let evt = mbox.mac_subsystem.read().await; | 115 | conf.assoc_short_address |
| 115 | info!("{:#x}", evt.mac_event()); | 116 | } else { |
| 116 | } | 117 | defmt::panic!() |
| 118 | }; | ||
| 119 | |||
| 120 | info!("{}", short_addr); | ||
| 117 | 121 | ||
| 118 | info!("Test OK"); | 122 | info!("Test OK"); |
| 119 | cortex_m::asm::bkpt(); | 123 | cortex_m::asm::bkpt(); |
