Merge pull request #1658 from xoviat/mac
implement most infra for wpan mac
This commit is contained in:
commit
4db63677f6
@ -164,6 +164,9 @@ pub enum Medium {
|
|||||||
///
|
///
|
||||||
/// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode.
|
/// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode.
|
||||||
Ip,
|
Ip,
|
||||||
|
|
||||||
|
/// IEEE 802_15_4 medium
|
||||||
|
Ieee802154,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Medium {
|
impl Default for Medium {
|
||||||
|
@ -37,6 +37,7 @@ proto-ipv4 = ["smoltcp/proto-ipv4"]
|
|||||||
proto-ipv6 = ["smoltcp/proto-ipv6"]
|
proto-ipv6 = ["smoltcp/proto-ipv6"]
|
||||||
medium-ethernet = ["smoltcp/medium-ethernet"]
|
medium-ethernet = ["smoltcp/medium-ethernet"]
|
||||||
medium-ip = ["smoltcp/medium-ip"]
|
medium-ip = ["smoltcp/medium-ip"]
|
||||||
|
medium-ieee802154 = ["smoltcp/medium-ieee802154"]
|
||||||
igmp = ["smoltcp/proto-igmp"]
|
igmp = ["smoltcp/proto-igmp"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -51,6 +51,8 @@ where
|
|||||||
Medium::Ethernet => phy::Medium::Ethernet,
|
Medium::Ethernet => phy::Medium::Ethernet,
|
||||||
#[cfg(feature = "medium-ip")]
|
#[cfg(feature = "medium-ip")]
|
||||||
Medium::Ip => phy::Medium::Ip,
|
Medium::Ip => phy::Medium::Ip,
|
||||||
|
#[cfg(feature = "medium-ieee802154")]
|
||||||
|
Medium::Ieee802154 => phy::Medium::Ieee802154,
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
"Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.",
|
"Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.",
|
||||||
|
@ -24,9 +24,11 @@ use embassy_net_driver::{Driver, LinkState, Medium};
|
|||||||
use embassy_sync::waitqueue::WakerRegistration;
|
use embassy_sync::waitqueue::WakerRegistration;
|
||||||
use embassy_time::{Instant, Timer};
|
use embassy_time::{Instant, Timer};
|
||||||
use futures::pin_mut;
|
use futures::pin_mut;
|
||||||
|
#[allow(unused_imports)]
|
||||||
use heapless::Vec;
|
use heapless::Vec;
|
||||||
#[cfg(feature = "igmp")]
|
#[cfg(feature = "igmp")]
|
||||||
pub use smoltcp::iface::MulticastError;
|
pub use smoltcp::iface::MulticastError;
|
||||||
|
#[allow(unused_imports)]
|
||||||
use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage};
|
use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage};
|
||||||
#[cfg(feature = "dhcpv4")]
|
#[cfg(feature = "dhcpv4")]
|
||||||
use smoltcp::socket::dhcpv4::{self, RetryConfig};
|
use smoltcp::socket::dhcpv4::{self, RetryConfig};
|
||||||
@ -34,6 +36,8 @@ use smoltcp::socket::dhcpv4::{self, RetryConfig};
|
|||||||
pub use smoltcp::wire::IpListenEndpoint;
|
pub use smoltcp::wire::IpListenEndpoint;
|
||||||
#[cfg(feature = "medium-ethernet")]
|
#[cfg(feature = "medium-ethernet")]
|
||||||
pub use smoltcp::wire::{EthernetAddress, HardwareAddress};
|
pub use smoltcp::wire::{EthernetAddress, HardwareAddress};
|
||||||
|
#[cfg(feature = "medium-ieee802154")]
|
||||||
|
pub use smoltcp::wire::{HardwareAddress, Ieee802154Address};
|
||||||
pub use smoltcp::wire::{IpAddress, IpCidr, IpEndpoint};
|
pub use smoltcp::wire::{IpAddress, IpCidr, IpEndpoint};
|
||||||
#[cfg(feature = "proto-ipv4")]
|
#[cfg(feature = "proto-ipv4")]
|
||||||
pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr};
|
pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr};
|
||||||
@ -232,7 +236,7 @@ impl<D: Driver + 'static> Stack<D> {
|
|||||||
resources: &'static mut StackResources<SOCK>,
|
resources: &'static mut StackResources<SOCK>,
|
||||||
random_seed: u64,
|
random_seed: u64,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
#[cfg(feature = "medium-ethernet")]
|
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
|
||||||
let medium = device.capabilities().medium;
|
let medium = device.capabilities().medium;
|
||||||
|
|
||||||
let hardware_addr = match medium {
|
let hardware_addr = match medium {
|
||||||
@ -240,6 +244,8 @@ impl<D: Driver + 'static> Stack<D> {
|
|||||||
Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress(device.ethernet_address())),
|
Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress(device.ethernet_address())),
|
||||||
#[cfg(feature = "medium-ip")]
|
#[cfg(feature = "medium-ip")]
|
||||||
Medium::Ip => HardwareAddress::Ip,
|
Medium::Ip => HardwareAddress::Ip,
|
||||||
|
#[cfg(feature = "medium-ieee802154")]
|
||||||
|
Medium::Ieee802154 => HardwareAddress::Ieee802154(Ieee802154Address::Absent),
|
||||||
#[allow(unreachable_patterns)]
|
#[allow(unreachable_patterns)]
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
"Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.",
|
"Unsupported medium {:?}. Make sure to enable it in embassy-net's Cargo features.",
|
||||||
@ -262,6 +268,7 @@ impl<D: Driver + 'static> Stack<D> {
|
|||||||
|
|
||||||
let next_local_port = (random_seed % (LOCAL_PORT_MAX - LOCAL_PORT_MIN) as u64) as u16 + LOCAL_PORT_MIN;
|
let next_local_port = (random_seed % (LOCAL_PORT_MAX - LOCAL_PORT_MIN) as u64) as u16 + LOCAL_PORT_MIN;
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "medium-ieee802154", allow(unused_mut))]
|
||||||
let mut socket = SocketStack {
|
let mut socket = SocketStack {
|
||||||
sockets,
|
sockets,
|
||||||
iface,
|
iface,
|
||||||
@ -269,6 +276,7 @@ impl<D: Driver + 'static> Stack<D> {
|
|||||||
next_local_port,
|
next_local_port,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "medium-ieee802154", allow(unused_mut))]
|
||||||
let mut inner = Inner {
|
let mut inner = Inner {
|
||||||
device,
|
device,
|
||||||
link_up: false,
|
link_up: false,
|
||||||
@ -287,6 +295,9 @@ impl<D: Driver + 'static> Stack<D> {
|
|||||||
dns_waker: WakerRegistration::new(),
|
dns_waker: WakerRegistration::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "medium-ieee802154")]
|
||||||
|
let _ = config;
|
||||||
|
|
||||||
#[cfg(feature = "proto-ipv4")]
|
#[cfg(feature = "proto-ipv4")]
|
||||||
match config.ipv4 {
|
match config.ipv4 {
|
||||||
ConfigV4::Static(config) => {
|
ConfigV4::Static(config) => {
|
||||||
|
@ -17,6 +17,7 @@ embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true }
|
|||||||
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
|
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
|
||||||
embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" }
|
embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" }
|
||||||
embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" }
|
embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" }
|
||||||
|
embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver", optional=true }
|
||||||
|
|
||||||
defmt = { version = "0.3", optional = true }
|
defmt = { version = "0.3", optional = true }
|
||||||
cortex-m = "0.7.6"
|
cortex-m = "0.7.6"
|
||||||
@ -26,13 +27,14 @@ aligned = "0.4.1"
|
|||||||
bit_field = "0.10.2"
|
bit_field = "0.10.2"
|
||||||
stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] }
|
stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] }
|
||||||
stm32wb-hci = { version = "0.1.3", optional = true }
|
stm32wb-hci = { version = "0.1.3", optional = true }
|
||||||
|
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
||||||
bitflags = { version = "2.3.3", optional = true }
|
bitflags = { version = "2.3.3", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"]
|
defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"]
|
||||||
|
|
||||||
ble = ["dep:stm32wb-hci"]
|
ble = ["dep:stm32wb-hci"]
|
||||||
mac = ["dep:bitflags"]
|
mac = ["dep:bitflags", "dep:embassy-net-driver" ]
|
||||||
|
|
||||||
stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ]
|
stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ]
|
||||||
stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ]
|
stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ]
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![cfg_attr(feature = "ble", feature(async_fn_in_trait))]
|
#![cfg_attr(any(feature = "ble", feature = "mac"), feature(async_fn_in_trait))]
|
||||||
|
#![cfg_attr(feature = "mac", feature(type_alias_impl_trait, concat_bytes))]
|
||||||
|
|
||||||
// This must go FIRST so that all the other modules see its macros.
|
// This must go FIRST so that all the other modules see its macros.
|
||||||
pub mod fmt;
|
pub mod fmt;
|
||||||
|
95
embassy-stm32-wpan/src/mac/control.rs
Normal file
95
embassy-stm32-wpan/src/mac/control.rs
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
use core::future::Future;
|
||||||
|
use core::task;
|
||||||
|
use core::task::Poll;
|
||||||
|
|
||||||
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
|
use embassy_sync::mutex::MutexGuard;
|
||||||
|
use embassy_sync::signal::Signal;
|
||||||
|
use futures::FutureExt;
|
||||||
|
|
||||||
|
use super::commands::MacCommand;
|
||||||
|
use super::event::MacEvent;
|
||||||
|
use super::typedefs::MacError;
|
||||||
|
use crate::mac::runner::Runner;
|
||||||
|
|
||||||
|
pub struct Control<'a> {
|
||||||
|
runner: &'a Runner<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Control<'a> {
|
||||||
|
pub(crate) fn new(runner: &'a Runner<'a>) -> Self {
|
||||||
|
Self { runner: runner }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError>
|
||||||
|
where
|
||||||
|
T: MacCommand,
|
||||||
|
{
|
||||||
|
let _wm = self.runner.write_mutex.lock().await;
|
||||||
|
|
||||||
|
self.runner.mac_subsystem.send_command(cmd).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_command_and_get_response<T>(&self, cmd: &T) -> Result<EventToken<'a>, MacError>
|
||||||
|
where
|
||||||
|
T: MacCommand,
|
||||||
|
{
|
||||||
|
let rm = self.runner.read_mutex.lock().await;
|
||||||
|
let _wm = self.runner.write_mutex.lock().await;
|
||||||
|
let token = EventToken::new(self.runner, rm);
|
||||||
|
|
||||||
|
self.runner.mac_subsystem.send_command(cmd).await?;
|
||||||
|
|
||||||
|
Ok(token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EventToken<'a> {
|
||||||
|
runner: &'a Runner<'a>,
|
||||||
|
_mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> EventToken<'a> {
|
||||||
|
pub(crate) fn new(runner: &'a Runner<'a>, mutex_guard: MutexGuard<'a, CriticalSectionRawMutex, ()>) -> Self {
|
||||||
|
// Enable event receiving
|
||||||
|
runner.rx_event_channel.lock(|s| {
|
||||||
|
*s.borrow_mut() = Some(Signal::new());
|
||||||
|
});
|
||||||
|
|
||||||
|
Self {
|
||||||
|
runner: runner,
|
||||||
|
_mutex_guard: mutex_guard,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Future for EventToken<'a> {
|
||||||
|
type Output = MacEvent<'a>;
|
||||||
|
|
||||||
|
fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
|
||||||
|
self.get_mut().runner.rx_event_channel.lock(|s| {
|
||||||
|
let signal = s.borrow_mut();
|
||||||
|
let signal = match &*signal {
|
||||||
|
Some(s) => s,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = match signal.wait().poll_unpin(cx) {
|
||||||
|
Poll::Ready(mac_event) => Poll::Ready(mac_event),
|
||||||
|
Poll::Pending => Poll::Pending,
|
||||||
|
};
|
||||||
|
|
||||||
|
result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Drop for EventToken<'a> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// Disable event receiving
|
||||||
|
// This will also drop the contained event, if it exists, and will free up receiving the next event
|
||||||
|
self.runner.rx_event_channel.lock(|s| {
|
||||||
|
*s.borrow_mut() = None;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
122
embassy-stm32-wpan/src/mac/driver.rs
Normal file
122
embassy-stm32-wpan/src/mac/driver.rs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#![allow(incomplete_features)]
|
||||||
|
#![deny(unused_must_use)]
|
||||||
|
|
||||||
|
use core::task::Context;
|
||||||
|
|
||||||
|
use embassy_net_driver::{Capabilities, LinkState, Medium};
|
||||||
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
|
use embassy_sync::channel::Channel;
|
||||||
|
|
||||||
|
use crate::mac::event::MacEvent;
|
||||||
|
use crate::mac::runner::Runner;
|
||||||
|
use crate::mac::MTU;
|
||||||
|
|
||||||
|
pub struct Driver<'d> {
|
||||||
|
runner: &'d Runner<'d>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> Driver<'d> {
|
||||||
|
pub(crate) fn new(runner: &'d Runner<'d>) -> Self {
|
||||||
|
Self { runner: runner }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> embassy_net_driver::Driver for Driver<'d> {
|
||||||
|
// type RxToken<'a> = RxToken<'a, 'd> where Self: 'a;
|
||||||
|
// type TxToken<'a> = TxToken<'a, 'd> where Self: 'a;
|
||||||
|
type RxToken<'a> = RxToken<'d> where Self: 'a;
|
||||||
|
type TxToken<'a> = TxToken<'d> where Self: 'a;
|
||||||
|
|
||||||
|
fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
|
||||||
|
if self.runner.rx_channel.poll_ready_to_receive(cx) && self.runner.tx_buf_channel.poll_ready_to_receive(cx) {
|
||||||
|
Some((
|
||||||
|
RxToken {
|
||||||
|
rx: &self.runner.rx_channel,
|
||||||
|
},
|
||||||
|
TxToken {
|
||||||
|
tx: &self.runner.tx_channel,
|
||||||
|
tx_buf: &self.runner.tx_buf_channel,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> {
|
||||||
|
if self.runner.tx_buf_channel.poll_ready_to_receive(cx) {
|
||||||
|
Some(TxToken {
|
||||||
|
tx: &self.runner.tx_channel,
|
||||||
|
tx_buf: &self.runner.tx_buf_channel,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn capabilities(&self) -> Capabilities {
|
||||||
|
let mut caps = Capabilities::default();
|
||||||
|
caps.max_transmission_unit = MTU;
|
||||||
|
// caps.max_burst_size = Some(self.tx.len());
|
||||||
|
|
||||||
|
caps.medium = Medium::Ieee802154;
|
||||||
|
caps
|
||||||
|
}
|
||||||
|
|
||||||
|
fn link_state(&mut self, _cx: &mut Context) -> LinkState {
|
||||||
|
// if self.phy.poll_link(&mut self.station_management, cx) {
|
||||||
|
// LinkState::Up
|
||||||
|
// } else {
|
||||||
|
// LinkState::Down
|
||||||
|
// }
|
||||||
|
|
||||||
|
LinkState::Down
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ethernet_address(&self) -> [u8; 6] {
|
||||||
|
// self.mac_addr
|
||||||
|
|
||||||
|
[0; 6]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RxToken<'d> {
|
||||||
|
rx: &'d Channel<CriticalSectionRawMutex, MacEvent<'d>, 1>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> embassy_net_driver::RxToken for RxToken<'d> {
|
||||||
|
fn consume<R, F>(self, f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut [u8]) -> R,
|
||||||
|
{
|
||||||
|
// Only valid data events should be put into the queue
|
||||||
|
|
||||||
|
let data_event = match self.rx.try_recv().unwrap() {
|
||||||
|
MacEvent::McpsDataInd(data_event) => data_event,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
f(&mut data_event.payload())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TxToken<'d> {
|
||||||
|
tx: &'d Channel<CriticalSectionRawMutex, (&'d mut [u8; MTU], usize), 5>,
|
||||||
|
tx_buf: &'d Channel<CriticalSectionRawMutex, &'d mut [u8; MTU], 5>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> embassy_net_driver::TxToken for TxToken<'d> {
|
||||||
|
fn consume<R, F>(self, len: usize, f: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut [u8]) -> R,
|
||||||
|
{
|
||||||
|
// Only valid tx buffers should be put into the queue
|
||||||
|
let buf = self.tx_buf.try_recv().unwrap();
|
||||||
|
let r = f(&mut buf[..len]);
|
||||||
|
|
||||||
|
// The tx channel should always be of equal capacity to the tx_buf channel
|
||||||
|
self.tx.try_send((buf, len)).unwrap();
|
||||||
|
|
||||||
|
r
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
use core::mem;
|
use core::{mem, ptr};
|
||||||
|
|
||||||
use super::indications::{
|
use super::indications::{
|
||||||
AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication,
|
AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication,
|
||||||
@ -8,9 +8,9 @@ use super::responses::{
|
|||||||
AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm,
|
AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm,
|
||||||
PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm,
|
PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm,
|
||||||
};
|
};
|
||||||
use crate::evt::EvtBox;
|
use crate::evt::{EvtBox, MemoryManager};
|
||||||
use crate::mac::opcodes::OpcodeM0ToM4;
|
use crate::mac::opcodes::OpcodeM0ToM4;
|
||||||
use crate::sub::mac::Mac;
|
use crate::sub::mac::{self, Mac};
|
||||||
|
|
||||||
pub(crate) trait ParseableMacEvent: Sized {
|
pub(crate) trait ParseableMacEvent: Sized {
|
||||||
fn from_buffer<'a>(buf: &'a [u8]) -> Result<&'a Self, ()> {
|
fn from_buffer<'a>(buf: &'a [u8]) -> Result<&'a Self, ()> {
|
||||||
@ -22,59 +22,8 @@ pub(crate) trait ParseableMacEvent: Sized {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Event {
|
|
||||||
event_box: EvtBox<Mac>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Event {
|
|
||||||
pub(crate) fn new(event_box: EvtBox<Mac>) -> Self {
|
|
||||||
Self { event_box }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mac_event<'a>(&'a self) -> Result<MacEvent<'a>, ()> {
|
|
||||||
let payload = self.event_box.payload();
|
|
||||||
let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap());
|
|
||||||
|
|
||||||
let opcode = OpcodeM0ToM4::try_from(opcode)?;
|
|
||||||
let buf = &payload[2..];
|
|
||||||
|
|
||||||
match opcode {
|
|
||||||
OpcodeM0ToM4::MlmeAssociateCnf => Ok(MacEvent::MlmeAssociateCnf(AssociateConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeDisassociateCnf => {
|
|
||||||
Ok(MacEvent::MlmeDisassociateCnf(DisassociateConfirm::from_buffer(buf)?))
|
|
||||||
}
|
|
||||||
OpcodeM0ToM4::MlmeGetCnf => Ok(MacEvent::MlmeGetCnf(GetConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeGtsCnf => Ok(MacEvent::MlmeGtsCnf(GtsConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeResetCnf => Ok(MacEvent::MlmeResetCnf(ResetConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeRxEnableCnf => Ok(MacEvent::MlmeRxEnableCnf(RxEnableConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeScanCnf => Ok(MacEvent::MlmeScanCnf(ScanConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeSetCnf => Ok(MacEvent::MlmeSetCnf(SetConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeStartCnf => Ok(MacEvent::MlmeStartCnf(StartConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmePollCnf => Ok(MacEvent::MlmePollCnf(PollConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeDpsCnf => Ok(MacEvent::MlmeDpsCnf(DpsConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeSoundingCnf => Ok(MacEvent::MlmeSoundingCnf(SoundingConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeCalibrateCnf => Ok(MacEvent::MlmeCalibrateCnf(CalibrateConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::McpsDataCnf => Ok(MacEvent::McpsDataCnf(DataConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::McpsPurgeCnf => Ok(MacEvent::McpsPurgeCnf(PurgeConfirm::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeAssociateInd => Ok(MacEvent::MlmeAssociateInd(AssociateIndication::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeDisassociateInd => {
|
|
||||||
Ok(MacEvent::MlmeDisassociateInd(DisassociateIndication::from_buffer(buf)?))
|
|
||||||
}
|
|
||||||
OpcodeM0ToM4::MlmeBeaconNotifyInd => {
|
|
||||||
Ok(MacEvent::MlmeBeaconNotifyInd(BeaconNotifyIndication::from_buffer(buf)?))
|
|
||||||
}
|
|
||||||
OpcodeM0ToM4::MlmeCommStatusInd => Ok(MacEvent::MlmeCommStatusInd(CommStatusIndication::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeGtsInd => Ok(MacEvent::MlmeGtsInd(GtsIndication::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeOrphanInd => Ok(MacEvent::MlmeOrphanInd(OrphanIndication::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeSyncLossInd => Ok(MacEvent::MlmeSyncLossInd(SyncLossIndication::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmeDpsInd => Ok(MacEvent::MlmeDpsInd(DpsIndication::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::McpsDataInd => Ok(MacEvent::McpsDataInd(DataIndication::from_buffer(buf)?)),
|
|
||||||
OpcodeM0ToM4::MlmePollInd => Ok(MacEvent::MlmePollInd(PollIndication::from_buffer(buf)?)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum MacEvent<'a> {
|
pub enum MacEvent<'a> {
|
||||||
MlmeAssociateCnf(&'a AssociateConfirm),
|
MlmeAssociateCnf(&'a AssociateConfirm),
|
||||||
MlmeDisassociateCnf(&'a DisassociateConfirm),
|
MlmeDisassociateCnf(&'a DisassociateConfirm),
|
||||||
@ -102,3 +51,103 @@ pub enum MacEvent<'a> {
|
|||||||
McpsDataInd(&'a DataIndication),
|
McpsDataInd(&'a DataIndication),
|
||||||
MlmePollInd(&'a PollIndication),
|
MlmePollInd(&'a PollIndication),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> MacEvent<'a> {
|
||||||
|
pub(crate) fn new(event_box: EvtBox<Mac>) -> Result<Self, ()> {
|
||||||
|
let payload = event_box.payload();
|
||||||
|
let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap());
|
||||||
|
|
||||||
|
let opcode = OpcodeM0ToM4::try_from(opcode)?;
|
||||||
|
let buf = &payload[2..];
|
||||||
|
|
||||||
|
// To avoid re-parsing the opcode, we store the result of the parse
|
||||||
|
// this requires use of unsafe because rust cannot assume that a reference will become
|
||||||
|
// invalid when the underlying result is moved. However, because we refer to a "heap"
|
||||||
|
// allocation, the underlying reference will not move until the struct is dropped.
|
||||||
|
|
||||||
|
let mac_event = match opcode {
|
||||||
|
OpcodeM0ToM4::MlmeAssociateCnf => {
|
||||||
|
MacEvent::MlmeAssociateCnf(unsafe { &*(AssociateConfirm::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeDisassociateCnf => {
|
||||||
|
MacEvent::MlmeDisassociateCnf(unsafe { &*(DisassociateConfirm::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeGetCnf => MacEvent::MlmeGetCnf(unsafe { &*(GetConfirm::from_buffer(buf)? as *const _) }),
|
||||||
|
OpcodeM0ToM4::MlmeGtsCnf => MacEvent::MlmeGtsCnf(unsafe { &*(GtsConfirm::from_buffer(buf)? as *const _) }),
|
||||||
|
OpcodeM0ToM4::MlmeResetCnf => {
|
||||||
|
MacEvent::MlmeResetCnf(unsafe { &*(ResetConfirm::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeRxEnableCnf => {
|
||||||
|
MacEvent::MlmeRxEnableCnf(unsafe { &*(RxEnableConfirm::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeScanCnf => {
|
||||||
|
MacEvent::MlmeScanCnf(unsafe { &*(ScanConfirm::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeSetCnf => MacEvent::MlmeSetCnf(unsafe { &*(SetConfirm::from_buffer(buf)? as *const _) }),
|
||||||
|
OpcodeM0ToM4::MlmeStartCnf => {
|
||||||
|
MacEvent::MlmeStartCnf(unsafe { &*(StartConfirm::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmePollCnf => {
|
||||||
|
MacEvent::MlmePollCnf(unsafe { &*(PollConfirm::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeDpsCnf => MacEvent::MlmeDpsCnf(unsafe { &*(DpsConfirm::from_buffer(buf)? as *const _) }),
|
||||||
|
OpcodeM0ToM4::MlmeSoundingCnf => {
|
||||||
|
MacEvent::MlmeSoundingCnf(unsafe { &*(SoundingConfirm::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeCalibrateCnf => {
|
||||||
|
MacEvent::MlmeCalibrateCnf(unsafe { &*(CalibrateConfirm::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::McpsDataCnf => {
|
||||||
|
MacEvent::McpsDataCnf(unsafe { &*(DataConfirm::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::McpsPurgeCnf => {
|
||||||
|
MacEvent::McpsPurgeCnf(unsafe { &*(PurgeConfirm::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeAssociateInd => {
|
||||||
|
MacEvent::MlmeAssociateInd(unsafe { &*(AssociateIndication::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeDisassociateInd => {
|
||||||
|
MacEvent::MlmeDisassociateInd(unsafe { &*(DisassociateIndication::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeBeaconNotifyInd => {
|
||||||
|
MacEvent::MlmeBeaconNotifyInd(unsafe { &*(BeaconNotifyIndication::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeCommStatusInd => {
|
||||||
|
MacEvent::MlmeCommStatusInd(unsafe { &*(CommStatusIndication::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeGtsInd => {
|
||||||
|
MacEvent::MlmeGtsInd(unsafe { &*(GtsIndication::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeOrphanInd => {
|
||||||
|
MacEvent::MlmeOrphanInd(unsafe { &*(OrphanIndication::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeSyncLossInd => {
|
||||||
|
MacEvent::MlmeSyncLossInd(unsafe { &*(SyncLossIndication::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmeDpsInd => {
|
||||||
|
MacEvent::MlmeDpsInd(unsafe { &*(DpsIndication::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::McpsDataInd => {
|
||||||
|
MacEvent::McpsDataInd(unsafe { &*(DataIndication::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
OpcodeM0ToM4::MlmePollInd => {
|
||||||
|
MacEvent::MlmePollInd(unsafe { &*(PollIndication::from_buffer(buf)? as *const _) })
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Forget the event box so that drop isn't called
|
||||||
|
// We want to handle the lifetime ourselves
|
||||||
|
|
||||||
|
mem::forget(event_box);
|
||||||
|
|
||||||
|
Ok(mac_event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<'a> Send for MacEvent<'a> {}
|
||||||
|
|
||||||
|
impl<'a> Drop for MacEvent<'a> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { mac::Mac::drop_event_packet(ptr::null_mut()) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@ use super::typedefs::{
|
|||||||
/// MLME ASSOCIATE Indication which will be used by the MAC
|
/// MLME ASSOCIATE Indication which will be used by the MAC
|
||||||
/// to indicate the reception of an association request command
|
/// to indicate the reception of an association request command
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct AssociateIndication {
|
pub struct AssociateIndication {
|
||||||
/// Extended address of the device requesting association
|
/// Extended address of the device requesting association
|
||||||
@ -31,6 +32,7 @@ impl ParseableMacEvent for AssociateIndication {}
|
|||||||
/// MLME DISASSOCIATE indication which will be used to send
|
/// MLME DISASSOCIATE indication which will be used to send
|
||||||
/// disassociation indication to the application.
|
/// disassociation indication to the application.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DisassociateIndication {
|
pub struct DisassociateIndication {
|
||||||
/// Extended address of the device requesting association
|
/// Extended address of the device requesting association
|
||||||
@ -52,6 +54,7 @@ impl ParseableMacEvent for DisassociateIndication {}
|
|||||||
/// MLME BEACON NOTIIFY Indication which is used to send parameters contained
|
/// MLME BEACON NOTIIFY Indication which is used to send parameters contained
|
||||||
/// within a beacon frame received by the MAC to the application
|
/// within a beacon frame received by the MAC to the application
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct BeaconNotifyIndication {
|
pub struct BeaconNotifyIndication {
|
||||||
/// he set of octets comprising the beacon payload to be transferred
|
/// he set of octets comprising the beacon payload to be transferred
|
||||||
@ -73,6 +76,7 @@ impl ParseableMacEvent for BeaconNotifyIndication {}
|
|||||||
|
|
||||||
/// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status
|
/// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct CommStatusIndication {
|
pub struct CommStatusIndication {
|
||||||
/// The 16-bit PAN identifier of the device from which the frame
|
/// The 16-bit PAN identifier of the device from which the frame
|
||||||
@ -103,6 +107,7 @@ impl ParseableMacEvent for CommStatusIndication {}
|
|||||||
/// MLME GTS Indication indicates that a GTS has been allocated or that a
|
/// MLME GTS Indication indicates that a GTS has been allocated or that a
|
||||||
/// previously allocated GTS has been deallocated
|
/// previously allocated GTS has been deallocated
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct GtsIndication {
|
pub struct GtsIndication {
|
||||||
/// The short address of the device that has been allocated or deallocated a GTS
|
/// The short address of the device that has been allocated or deallocated a GTS
|
||||||
@ -126,6 +131,7 @@ impl ParseableMacEvent for GtsIndication {}
|
|||||||
/// MLME ORPHAN Indication which is used by the coordinator to notify the
|
/// MLME ORPHAN Indication which is used by the coordinator to notify the
|
||||||
/// application of the presence of an orphaned device
|
/// application of the presence of an orphaned device
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct OrphanIndication {
|
pub struct OrphanIndication {
|
||||||
/// Extended address of the orphaned device
|
/// Extended address of the orphaned device
|
||||||
@ -147,6 +153,7 @@ impl ParseableMacEvent for OrphanIndication {}
|
|||||||
/// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss
|
/// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss
|
||||||
/// of synchronization with the coordinator
|
/// of synchronization with the coordinator
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct SyncLossIndication {
|
pub struct SyncLossIndication {
|
||||||
/// The PAN identifier with which the device lost synchronization or to which it was realigned
|
/// The PAN identifier with which the device lost synchronization or to which it was realigned
|
||||||
@ -172,6 +179,7 @@ impl ParseableMacEvent for SyncLossIndication {}
|
|||||||
/// MLME DPS Indication which indicates the expiration of the DPSIndexDuration
|
/// MLME DPS Indication which indicates the expiration of the DPSIndexDuration
|
||||||
/// and the resetting of the DPS values in the PHY
|
/// and the resetting of the DPS values in the PHY
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DpsIndication {
|
pub struct DpsIndication {
|
||||||
/// byte stuffing to keep 32 bit alignment
|
/// byte stuffing to keep 32 bit alignment
|
||||||
@ -181,6 +189,7 @@ pub struct DpsIndication {
|
|||||||
impl ParseableMacEvent for DpsIndication {}
|
impl ParseableMacEvent for DpsIndication {}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DataIndication {
|
pub struct DataIndication {
|
||||||
/// Pointer to the set of octets forming the MSDU being indicated
|
/// Pointer to the set of octets forming the MSDU being indicated
|
||||||
@ -236,14 +245,15 @@ pub struct DataIndication {
|
|||||||
impl ParseableMacEvent for DataIndication {}
|
impl ParseableMacEvent for DataIndication {}
|
||||||
|
|
||||||
impl DataIndication {
|
impl DataIndication {
|
||||||
pub fn payload<'a>(&'a self) -> &'a [u8] {
|
pub fn payload<'a>(&'a self) -> &'a mut [u8] {
|
||||||
unsafe { slice::from_raw_parts(self.msdu_ptr, self.msdu_length as usize) }
|
unsafe { slice::from_raw_parts_mut(self.msdu_ptr as *mut _, self.msdu_length as usize) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// MLME POLL Indication which will be used for indicating the Data Request
|
/// MLME POLL Indication which will be used for indicating the Data Request
|
||||||
/// reception to upper layer as defined in Zigbee r22 - D.8.2
|
/// reception to upper layer as defined in Zigbee r22 - D.8.2
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct PollIndication {
|
pub struct PollIndication {
|
||||||
/// addressing mode used
|
/// addressing mode used
|
||||||
|
@ -1,8 +1,21 @@
|
|||||||
pub mod commands;
|
pub mod commands;
|
||||||
mod consts;
|
mod consts;
|
||||||
|
pub mod control;
|
||||||
|
mod driver;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod indications;
|
pub mod indications;
|
||||||
mod macros;
|
mod macros;
|
||||||
mod opcodes;
|
mod opcodes;
|
||||||
pub mod responses;
|
pub mod responses;
|
||||||
|
pub mod runner;
|
||||||
pub mod typedefs;
|
pub mod typedefs;
|
||||||
|
|
||||||
|
pub use crate::mac::control::Control;
|
||||||
|
use crate::mac::driver::Driver;
|
||||||
|
pub use crate::mac::runner::Runner;
|
||||||
|
|
||||||
|
const MTU: usize = 127;
|
||||||
|
|
||||||
|
pub async fn new<'a>(runner: &'a Runner<'a>) -> (Control<'a>, Driver<'a>) {
|
||||||
|
(Control::new(runner), Driver::new(runner))
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ use super::typedefs::{
|
|||||||
/// MLME ASSOCIATE Confirm used to inform of the initiating device whether
|
/// MLME ASSOCIATE Confirm used to inform of the initiating device whether
|
||||||
/// its request to associate was successful or unsuccessful
|
/// its request to associate was successful or unsuccessful
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct AssociateConfirm {
|
pub struct AssociateConfirm {
|
||||||
/// short address allocated by the coordinator on successful association
|
/// short address allocated by the coordinator on successful association
|
||||||
@ -30,6 +31,7 @@ impl ParseableMacEvent for AssociateConfirm {}
|
|||||||
|
|
||||||
/// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application.
|
/// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DisassociateConfirm {
|
pub struct DisassociateConfirm {
|
||||||
/// status of the disassociation attempt
|
/// status of the disassociation attempt
|
||||||
@ -46,6 +48,7 @@ impl ParseableMacEvent for DisassociateConfirm {}
|
|||||||
|
|
||||||
/// MLME GET Confirm which requests information about a given PIB attribute
|
/// MLME GET Confirm which requests information about a given PIB attribute
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct GetConfirm {
|
pub struct GetConfirm {
|
||||||
/// The pointer to the value of the PIB attribute attempted to read
|
/// The pointer to the value of the PIB attribute attempted to read
|
||||||
@ -65,6 +68,7 @@ impl ParseableMacEvent for GetConfirm {}
|
|||||||
/// MLME GTS Confirm which eports the results of a request to allocate a new GTS
|
/// MLME GTS Confirm which eports the results of a request to allocate a new GTS
|
||||||
/// or to deallocate an existing GTS
|
/// or to deallocate an existing GTS
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct GtsConfirm {
|
pub struct GtsConfirm {
|
||||||
/// The characteristics of the GTS
|
/// The characteristics of the GTS
|
||||||
@ -79,10 +83,11 @@ impl ParseableMacEvent for GtsConfirm {}
|
|||||||
|
|
||||||
/// MLME RESET Confirm which is used to report the results of the reset operation
|
/// MLME RESET Confirm which is used to report the results of the reset operation
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct ResetConfirm {
|
pub struct ResetConfirm {
|
||||||
/// The result of the reset operation
|
/// The result of the reset operation
|
||||||
status: MacStatus,
|
pub status: MacStatus,
|
||||||
/// byte stuffing to keep 32 bit alignment
|
/// byte stuffing to keep 32 bit alignment
|
||||||
a_stuffing: [u8; 3],
|
a_stuffing: [u8; 3],
|
||||||
}
|
}
|
||||||
@ -92,10 +97,11 @@ impl ParseableMacEvent for ResetConfirm {}
|
|||||||
/// MLME RX ENABLE Confirm which is used to report the results of the attempt
|
/// MLME RX ENABLE Confirm which is used to report the results of the attempt
|
||||||
/// to enable or disable the receiver
|
/// to enable or disable the receiver
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct RxEnableConfirm {
|
pub struct RxEnableConfirm {
|
||||||
/// Result of the request to enable or disable the receiver
|
/// Result of the request to enable or disable the receiver
|
||||||
status: MacStatus,
|
pub status: MacStatus,
|
||||||
/// byte stuffing to keep 32 bit alignment
|
/// byte stuffing to keep 32 bit alignment
|
||||||
a_stuffing: [u8; 3],
|
a_stuffing: [u8; 3],
|
||||||
}
|
}
|
||||||
@ -104,6 +110,7 @@ impl ParseableMacEvent for RxEnableConfirm {}
|
|||||||
|
|
||||||
/// MLME SCAN Confirm which is used to report the result of the channel scan request
|
/// MLME SCAN Confirm which is used to report the result of the channel scan request
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct ScanConfirm {
|
pub struct ScanConfirm {
|
||||||
/// Status of the scan request
|
/// Status of the scan request
|
||||||
@ -130,6 +137,7 @@ impl ParseableMacEvent for ScanConfirm {}
|
|||||||
|
|
||||||
/// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute
|
/// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct SetConfirm {
|
pub struct SetConfirm {
|
||||||
/// The result of the set operation
|
/// The result of the set operation
|
||||||
@ -145,6 +153,7 @@ impl ParseableMacEvent for SetConfirm {}
|
|||||||
/// MLME START Confirm which is used to report the results of the attempt to
|
/// MLME START Confirm which is used to report the results of the attempt to
|
||||||
/// start using a new superframe configuration
|
/// start using a new superframe configuration
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct StartConfirm {
|
pub struct StartConfirm {
|
||||||
/// Result of the attempt to start using an updated superframe configuration
|
/// Result of the attempt to start using an updated superframe configuration
|
||||||
@ -157,6 +166,7 @@ impl ParseableMacEvent for StartConfirm {}
|
|||||||
|
|
||||||
/// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data
|
/// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct PollConfirm {
|
pub struct PollConfirm {
|
||||||
/// The status of the data request
|
/// The status of the data request
|
||||||
@ -169,6 +179,7 @@ impl ParseableMacEvent for PollConfirm {}
|
|||||||
|
|
||||||
/// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS
|
/// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DpsConfirm {
|
pub struct DpsConfirm {
|
||||||
/// The status of the DPS request
|
/// The status of the DPS request
|
||||||
@ -182,10 +193,11 @@ impl ParseableMacEvent for DpsConfirm {}
|
|||||||
/// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide
|
/// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide
|
||||||
/// channel sounding information
|
/// channel sounding information
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct SoundingConfirm {
|
pub struct SoundingConfirm {
|
||||||
/// Results of the sounding measurement
|
/// Results of the sounding measurement
|
||||||
sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED],
|
pub sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED],
|
||||||
|
|
||||||
status: u8,
|
status: u8,
|
||||||
}
|
}
|
||||||
@ -195,6 +207,7 @@ impl ParseableMacEvent for SoundingConfirm {}
|
|||||||
/// MLME CALIBRATE Confirm which reports the result of a request to the PHY
|
/// MLME CALIBRATE Confirm which reports the result of a request to the PHY
|
||||||
/// to provide internal propagation path information
|
/// to provide internal propagation path information
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct CalibrateConfirm {
|
pub struct CalibrateConfirm {
|
||||||
/// The status of the attempt to return sounding data
|
/// The status of the attempt to return sounding data
|
||||||
@ -214,6 +227,7 @@ impl ParseableMacEvent for CalibrateConfirm {}
|
|||||||
/// MCPS DATA Confirm which will be used for reporting the results of
|
/// MCPS DATA Confirm which will be used for reporting the results of
|
||||||
/// MAC data related requests from the application
|
/// MAC data related requests from the application
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct DataConfirm {
|
pub struct DataConfirm {
|
||||||
/// The handle associated with the MSDU being confirmed
|
/// The handle associated with the MSDU being confirmed
|
||||||
@ -245,6 +259,7 @@ impl ParseableMacEvent for DataConfirm {}
|
|||||||
/// MCPS PURGE Confirm which will be used by the MAC to notify the application of
|
/// MCPS PURGE Confirm which will be used by the MAC to notify the application of
|
||||||
/// the status of its request to purge an MSDU from the transaction queue
|
/// the status of its request to purge an MSDU from the transaction queue
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct PurgeConfirm {
|
pub struct PurgeConfirm {
|
||||||
/// Handle associated with the MSDU requested to be purged from the transaction queue
|
/// Handle associated with the MSDU requested to be purged from the transaction queue
|
||||||
|
109
embassy-stm32-wpan/src/mac/runner.rs
Normal file
109
embassy-stm32-wpan/src/mac/runner.rs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
use core::cell::RefCell;
|
||||||
|
|
||||||
|
use embassy_futures::join;
|
||||||
|
use embassy_sync::blocking_mutex;
|
||||||
|
use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
|
||||||
|
use embassy_sync::channel::Channel;
|
||||||
|
use embassy_sync::mutex::Mutex;
|
||||||
|
use embassy_sync::signal::Signal;
|
||||||
|
|
||||||
|
use crate::mac::commands::DataRequest;
|
||||||
|
use crate::mac::event::MacEvent;
|
||||||
|
use crate::mac::typedefs::{AddressMode, MacAddress, PanId, SecurityLevel};
|
||||||
|
use crate::mac::MTU;
|
||||||
|
use crate::sub::mac::Mac;
|
||||||
|
|
||||||
|
type ZeroCopyPubSub<M, T> = blocking_mutex::Mutex<M, RefCell<Option<Signal<NoopRawMutex, T>>>>;
|
||||||
|
|
||||||
|
pub struct Runner<'a> {
|
||||||
|
pub(crate) mac_subsystem: Mac,
|
||||||
|
// rx event backpressure is already provided through the MacEvent drop mechanism
|
||||||
|
// therefore, we don't need to worry about overwriting events
|
||||||
|
pub(crate) rx_event_channel: ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>,
|
||||||
|
pub(crate) read_mutex: Mutex<CriticalSectionRawMutex, ()>,
|
||||||
|
pub(crate) write_mutex: Mutex<CriticalSectionRawMutex, ()>,
|
||||||
|
pub(crate) rx_channel: Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>,
|
||||||
|
pub(crate) tx_channel: Channel<CriticalSectionRawMutex, (&'a mut [u8; MTU], usize), 5>,
|
||||||
|
pub(crate) tx_buf_channel: Channel<CriticalSectionRawMutex, &'a mut [u8; MTU], 5>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Runner<'a> {
|
||||||
|
pub fn new(mac: Mac, tx_buf_queue: [&'a mut [u8; MTU]; 5]) -> Self {
|
||||||
|
let this = Self {
|
||||||
|
mac_subsystem: mac,
|
||||||
|
rx_event_channel: blocking_mutex::Mutex::new(RefCell::new(None)),
|
||||||
|
read_mutex: Mutex::new(()),
|
||||||
|
write_mutex: Mutex::new(()),
|
||||||
|
rx_channel: Channel::new(),
|
||||||
|
tx_channel: Channel::new(),
|
||||||
|
tx_buf_channel: Channel::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
for buf in tx_buf_queue {
|
||||||
|
this.tx_buf_channel.try_send(buf).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run(&'a self) -> ! {
|
||||||
|
join::join(
|
||||||
|
async {
|
||||||
|
loop {
|
||||||
|
if let Ok(mac_event) = self.mac_subsystem.read().await {
|
||||||
|
match mac_event {
|
||||||
|
MacEvent::McpsDataInd(_) => {
|
||||||
|
self.rx_channel.send(mac_event).await;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.rx_event_channel.lock(|s| {
|
||||||
|
match &*s.borrow() {
|
||||||
|
Some(signal) => {
|
||||||
|
signal.signal(mac_event);
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async {
|
||||||
|
let mut msdu_handle = 0x02;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let (buf, len) = self.tx_channel.recv().await;
|
||||||
|
let _wm = self.write_mutex.lock().await;
|
||||||
|
|
||||||
|
// The mutex should be dropped on the next loop iteration
|
||||||
|
self.mac_subsystem
|
||||||
|
.send_command(
|
||||||
|
DataRequest {
|
||||||
|
src_addr_mode: AddressMode::Short,
|
||||||
|
dst_addr_mode: AddressMode::Short,
|
||||||
|
dst_pan_id: PanId([0x1A, 0xAA]),
|
||||||
|
dst_address: MacAddress::BROADCAST,
|
||||||
|
msdu_handle: msdu_handle,
|
||||||
|
ack_tx: 0x00,
|
||||||
|
gts_tx: false,
|
||||||
|
security_level: SecurityLevel::Unsecure,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.set_buffer(&buf[..len]),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
msdu_handle = msdu_handle.wrapping_add(1);
|
||||||
|
|
||||||
|
// The tx channel should always be of equal capacity to the tx_buf channel
|
||||||
|
self.tx_buf_channel.try_send(buf).unwrap();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
use core::fmt::Debug;
|
||||||
|
|
||||||
use crate::numeric_enum;
|
use crate::numeric_enum;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -37,7 +39,7 @@ numeric_enum! {
|
|||||||
numeric_enum! {
|
numeric_enum! {
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
/// this enum contains all the MAC PIB Ids
|
/// this enum contains all the MAC PIB Ids
|
||||||
#[derive(Default)]
|
#[derive(Default, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum PibId {
|
pub enum PibId {
|
||||||
// PHY
|
// PHY
|
||||||
@ -96,7 +98,7 @@ numeric_enum! {
|
|||||||
|
|
||||||
numeric_enum! {
|
numeric_enum! {
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum AddressMode {
|
pub enum AddressMode {
|
||||||
#[default]
|
#[default]
|
||||||
@ -113,6 +115,18 @@ pub union MacAddress {
|
|||||||
pub extended: [u8; 8],
|
pub extended: [u8; 8],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for MacAddress {
|
||||||
|
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
unsafe {
|
||||||
|
write!(
|
||||||
|
fmt,
|
||||||
|
"MacAddress {{ short: {:?}, extended: {:?} }}",
|
||||||
|
self.short, self.extended
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "defmt")]
|
#[cfg(feature = "defmt")]
|
||||||
impl defmt::Format for MacAddress {
|
impl defmt::Format for MacAddress {
|
||||||
fn format(&self, fmt: defmt::Formatter) {
|
fn format(&self, fmt: defmt::Formatter) {
|
||||||
@ -159,7 +173,7 @@ pub struct GtsCharacteristics {
|
|||||||
|
|
||||||
/// MAC PAN Descriptor which contains the network details of the device from
|
/// MAC PAN Descriptor which contains the network details of the device from
|
||||||
/// which the beacon is received
|
/// which the beacon is received
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct PanDescriptor {
|
pub struct PanDescriptor {
|
||||||
/// PAN identifier of the coordinator
|
/// PAN identifier of the coordinator
|
||||||
@ -223,7 +237,7 @@ impl TryFrom<&[u8]> for PanDescriptor {
|
|||||||
|
|
||||||
numeric_enum! {
|
numeric_enum! {
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
/// Building wireless applications with STM32WB series MCUs - Application note 13.10.3
|
/// Building wireless applications with STM32WB series MCUs - Application note 13.10.3
|
||||||
pub enum MacChannel {
|
pub enum MacChannel {
|
||||||
@ -289,7 +303,7 @@ defmt::bitflags! {
|
|||||||
|
|
||||||
numeric_enum! {
|
numeric_enum! {
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum KeyIdMode {
|
pub enum KeyIdMode {
|
||||||
#[default]
|
#[default]
|
||||||
@ -306,6 +320,7 @@ numeric_enum! {
|
|||||||
|
|
||||||
numeric_enum! {
|
numeric_enum! {
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum AssociationStatus {
|
pub enum AssociationStatus {
|
||||||
/// Association successful
|
/// Association successful
|
||||||
@ -319,7 +334,7 @@ numeric_enum! {
|
|||||||
|
|
||||||
numeric_enum! {
|
numeric_enum! {
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum DisassociationReason {
|
pub enum DisassociationReason {
|
||||||
/// The coordinator wishes the device to leave the PAN.
|
/// The coordinator wishes the device to leave the PAN.
|
||||||
@ -331,7 +346,7 @@ numeric_enum! {
|
|||||||
|
|
||||||
numeric_enum! {
|
numeric_enum! {
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum SecurityLevel {
|
pub enum SecurityLevel {
|
||||||
/// MAC Unsecured Mode Security
|
/// MAC Unsecured Mode Security
|
||||||
@ -346,6 +361,7 @@ numeric_enum! {
|
|||||||
|
|
||||||
numeric_enum! {
|
numeric_enum! {
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
#[derive(Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum ScanType {
|
pub enum ScanType {
|
||||||
EdScan = 0x00,
|
EdScan = 0x00,
|
||||||
@ -356,7 +372,7 @@ numeric_enum! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// newtype for Pan Id
|
/// newtype for Pan Id
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct PanId(pub [u8; 2]);
|
pub struct PanId(pub [u8; 2]);
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use crate::cmd::CmdPacket;
|
|||||||
use crate::consts::TlPacketType;
|
use crate::consts::TlPacketType;
|
||||||
use crate::evt::{EvtBox, EvtPacket};
|
use crate::evt::{EvtBox, EvtPacket};
|
||||||
use crate::mac::commands::MacCommand;
|
use crate::mac::commands::MacCommand;
|
||||||
use crate::mac::event::Event;
|
use crate::mac::event::MacEvent;
|
||||||
use crate::mac::typedefs::MacError;
|
use crate::mac::typedefs::MacError;
|
||||||
use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER};
|
use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER};
|
||||||
use crate::{channels, evt};
|
use crate::{channels, evt};
|
||||||
@ -94,14 +94,16 @@ impl Mac {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read(&self) -> Event {
|
pub async fn read(&self) -> Result<MacEvent<'_>, ()> {
|
||||||
Event::new(self.tl_read().await)
|
MacEvent::new(self.tl_read().await)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl evt::MemoryManager for Mac {
|
impl evt::MemoryManager for Mac {
|
||||||
/// SAFETY: passing a pointer to something other than a managed event packet is UB
|
/// SAFETY: passing a pointer to something other than a managed event packet is UB
|
||||||
unsafe fn drop_event_packet(_: *mut EvtPacket) {
|
unsafe fn drop_event_packet(_: *mut EvtPacket) {
|
||||||
|
trace!("mac drop event");
|
||||||
|
|
||||||
// Write the ack
|
// Write the ack
|
||||||
CmdPacket::write_into(
|
CmdPacket::write_into(
|
||||||
MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _,
|
MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _,
|
||||||
@ -111,7 +113,7 @@ impl evt::MemoryManager for Mac {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Clear the rx flag
|
// Clear the rx flag
|
||||||
let _ = poll_once(Ipcc::receive::<bool>(
|
let _ = poll_once(Ipcc::receive::<()>(
|
||||||
channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL,
|
channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL,
|
||||||
|| None,
|
|| None,
|
||||||
));
|
));
|
||||||
|
@ -335,6 +335,12 @@ impl<T, const N: usize> ChannelState<T, N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poll_ready_to_receive(&mut self, cx: &mut Context<'_>) -> bool {
|
||||||
|
self.receiver_waker.register(cx.waker());
|
||||||
|
|
||||||
|
!self.queue.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
fn try_send(&mut self, message: T) -> Result<(), TrySendError<T>> {
|
fn try_send(&mut self, message: T) -> Result<(), TrySendError<T>> {
|
||||||
self.try_send_with_context(message, None)
|
self.try_send_with_context(message, None)
|
||||||
}
|
}
|
||||||
@ -353,6 +359,12 @@ impl<T, const N: usize> ChannelState<T, N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poll_ready_to_send(&mut self, cx: &mut Context<'_>) -> bool {
|
||||||
|
self.senders_waker.register(cx.waker());
|
||||||
|
|
||||||
|
!self.queue.is_full()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A bounded channel for communicating between asynchronous tasks
|
/// A bounded channel for communicating between asynchronous tasks
|
||||||
@ -401,6 +413,16 @@ where
|
|||||||
self.lock(|c| c.try_send_with_context(m, cx))
|
self.lock(|c| c.try_send_with_context(m, cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Allows a poll_fn to poll until the channel is ready to receive
|
||||||
|
pub fn poll_ready_to_receive(&self, cx: &mut Context<'_>) -> bool {
|
||||||
|
self.lock(|c| c.poll_ready_to_receive(cx))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Allows a poll_fn to poll until the channel is ready to send
|
||||||
|
pub fn poll_ready_to_send(&self, cx: &mut Context<'_>) -> bool {
|
||||||
|
self.lock(|c| c.poll_ready_to_send(cx))
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a sender for this channel.
|
/// Get a sender for this channel.
|
||||||
pub fn sender(&self) -> Sender<'_, M, T, N> {
|
pub fn sender(&self) -> Sender<'_, M, T, N> {
|
||||||
Sender { channel: self }
|
Sender { channel: self }
|
||||||
|
@ -10,6 +10,7 @@ embassy-executor = { version = "0.2.0", path = "../../embassy-executor", feature
|
|||||||
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] }
|
||||||
embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] }
|
embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] }
|
||||||
|
embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ieee802154", "nightly"], optional=true }
|
||||||
|
|
||||||
defmt = "0.3"
|
defmt = "0.3"
|
||||||
defmt-rtt = "0.4"
|
defmt-rtt = "0.4"
|
||||||
@ -20,11 +21,11 @@ embedded-hal = "0.2.6"
|
|||||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||||
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
||||||
heapless = { version = "0.7.5", default-features = false }
|
heapless = { version = "0.7.5", default-features = false }
|
||||||
|
static_cell = { version = "1.1", features = ["nightly"]}
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["ble", "mac"]
|
default = ["ble", "mac"]
|
||||||
mac = ["embassy-stm32-wpan/mac"]
|
mac = ["embassy-stm32-wpan/mac", "dep:embassy-net"]
|
||||||
ble = ["embassy-stm32-wpan/ble"]
|
ble = ["embassy-stm32-wpan/ble"]
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
@ -39,6 +40,10 @@ required-features = ["mac"]
|
|||||||
name = "mac_ffd"
|
name = "mac_ffd"
|
||||||
required-features = ["mac"]
|
required-features = ["mac"]
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "mac_ffd_net"
|
||||||
|
required-features = ["mac"]
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "eddystone_beacon"
|
name = "eddystone_beacon"
|
||||||
required-features = ["ble"]
|
required-features = ["ble"]
|
||||||
|
@ -73,10 +73,7 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
|
||||||
defmt::info!("{:#x}", evt.mac_event());
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("setting extended address");
|
info!("setting extended address");
|
||||||
let extended_address: u64 = 0xACDE480000000001;
|
let extended_address: u64 = 0xACDE480000000001;
|
||||||
@ -87,10 +84,7 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
|
||||||
defmt::info!("{:#x}", evt.mac_event());
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("setting short address");
|
info!("setting short address");
|
||||||
let short_address: u16 = 0x1122;
|
let short_address: u16 = 0x1122;
|
||||||
@ -101,10 +95,7 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
|
||||||
defmt::info!("{:#x}", evt.mac_event());
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("setting association permit");
|
info!("setting association permit");
|
||||||
let association_permit: bool = true;
|
let association_permit: bool = true;
|
||||||
@ -115,10 +106,7 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
|
||||||
defmt::info!("{:#x}", evt.mac_event());
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("setting TX power");
|
info!("setting TX power");
|
||||||
let transmit_power: i8 = 2;
|
let transmit_power: i8 = 2;
|
||||||
@ -129,10 +117,7 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
|
||||||
defmt::info!("{:#x}", evt.mac_event());
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("starting FFD device");
|
info!("starting FFD device");
|
||||||
mbox.mac_subsystem
|
mbox.mac_subsystem
|
||||||
@ -147,10 +132,7 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
|
||||||
defmt::info!("{:#x}", evt.mac_event());
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("setting RX on when idle");
|
info!("setting RX on when idle");
|
||||||
let rx_on_while_idle: bool = true;
|
let rx_on_while_idle: bool = true;
|
||||||
@ -161,14 +143,11 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
|
||||||
defmt::info!("{:#x}", evt.mac_event());
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
let evt = mbox.mac_subsystem.read().await;
|
||||||
if let Ok(evt) = evt.mac_event() {
|
if let Ok(evt) = evt {
|
||||||
defmt::info!("parsed mac event");
|
defmt::info!("parsed mac event");
|
||||||
defmt::info!("{:#x}", evt);
|
defmt::info!("{:#x}", evt);
|
||||||
|
|
||||||
|
170
examples/stm32wb/src/bin/mac_ffd_net.rs
Normal file
170
examples/stm32wb/src/bin/mac_ffd_net.rs
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::bind_interrupts;
|
||||||
|
use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
|
||||||
|
use embassy_stm32_wpan::mac::commands::{ResetRequest, SetRequest, StartRequest};
|
||||||
|
use embassy_stm32_wpan::mac::typedefs::{MacChannel, PanId, PibId};
|
||||||
|
use embassy_stm32_wpan::mac::{self, Runner};
|
||||||
|
use embassy_stm32_wpan::sub::mm;
|
||||||
|
use embassy_stm32_wpan::TlMbox;
|
||||||
|
use static_cell::make_static;
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs{
|
||||||
|
IPCC_C1_RX => ReceiveInterruptHandler;
|
||||||
|
IPCC_C1_TX => TransmitInterruptHandler;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn run_mm_queue(memory_manager: mm::MemoryManager) {
|
||||||
|
memory_manager.run_queue().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn run_mac(runner: &'static Runner<'static>) {
|
||||||
|
runner.run().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(spawner: Spawner) {
|
||||||
|
/*
|
||||||
|
How to make this work:
|
||||||
|
|
||||||
|
- Obtain a NUCLEO-STM32WB55 from your preferred supplier.
|
||||||
|
- Download and Install STM32CubeProgrammer.
|
||||||
|
- Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from
|
||||||
|
gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x
|
||||||
|
- Open STM32CubeProgrammer
|
||||||
|
- On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware.
|
||||||
|
- Once complete, click connect to connect to the device.
|
||||||
|
- On the left hand pane, click the RSS signal icon to open "Firmware Upgrade Services".
|
||||||
|
- In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file
|
||||||
|
- Select that file, the memory address, "verify download", and then "Firmware Upgrade".
|
||||||
|
- Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the
|
||||||
|
stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address.
|
||||||
|
- Select that file, the memory address, "verify download", and then "Firmware Upgrade".
|
||||||
|
- Select "Start Wireless Stack".
|
||||||
|
- Disconnect from the device.
|
||||||
|
- In the examples folder for stm32wb, modify the memory.x file to match your target device.
|
||||||
|
- Run this example.
|
||||||
|
|
||||||
|
Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
info!("Hello World!");
|
||||||
|
|
||||||
|
let config = Config::default();
|
||||||
|
let mbox = TlMbox::init(p.IPCC, Irqs, config);
|
||||||
|
|
||||||
|
spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap();
|
||||||
|
|
||||||
|
let sys_event = mbox.sys_subsystem.read().await;
|
||||||
|
info!("sys event: {}", sys_event.payload());
|
||||||
|
|
||||||
|
core::mem::drop(sys_event);
|
||||||
|
|
||||||
|
let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await;
|
||||||
|
info!("initialized mac: {}", result);
|
||||||
|
|
||||||
|
info!("resetting");
|
||||||
|
mbox.mac_subsystem
|
||||||
|
.send_command(&ResetRequest {
|
||||||
|
set_default_pib: true,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
|
|
||||||
|
info!("setting extended address");
|
||||||
|
let extended_address: u64 = 0xACDE480000000001;
|
||||||
|
mbox.mac_subsystem
|
||||||
|
.send_command(&SetRequest {
|
||||||
|
pib_attribute_ptr: &extended_address as *const _ as *const u8,
|
||||||
|
pib_attribute: PibId::ExtendedAddress,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
|
|
||||||
|
info!("setting short address");
|
||||||
|
let short_address: u16 = 0x1122;
|
||||||
|
mbox.mac_subsystem
|
||||||
|
.send_command(&SetRequest {
|
||||||
|
pib_attribute_ptr: &short_address as *const _ as *const u8,
|
||||||
|
pib_attribute: PibId::ShortAddress,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
|
|
||||||
|
info!("setting association permit");
|
||||||
|
let association_permit: bool = true;
|
||||||
|
mbox.mac_subsystem
|
||||||
|
.send_command(&SetRequest {
|
||||||
|
pib_attribute_ptr: &association_permit as *const _ as *const u8,
|
||||||
|
pib_attribute: PibId::AssociationPermit,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
|
|
||||||
|
info!("setting TX power");
|
||||||
|
let transmit_power: i8 = 2;
|
||||||
|
mbox.mac_subsystem
|
||||||
|
.send_command(&SetRequest {
|
||||||
|
pib_attribute_ptr: &transmit_power as *const _ as *const u8,
|
||||||
|
pib_attribute: PibId::TransmitPower,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
|
|
||||||
|
info!("starting FFD device");
|
||||||
|
mbox.mac_subsystem
|
||||||
|
.send_command(&StartRequest {
|
||||||
|
pan_id: PanId([0x1A, 0xAA]),
|
||||||
|
channel_number: MacChannel::Channel16,
|
||||||
|
beacon_order: 0x0F,
|
||||||
|
superframe_order: 0x0F,
|
||||||
|
pan_coordinator: true,
|
||||||
|
battery_life_extension: false,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
|
|
||||||
|
info!("setting RX on when idle");
|
||||||
|
let rx_on_while_idle: bool = true;
|
||||||
|
mbox.mac_subsystem
|
||||||
|
.send_command(&SetRequest {
|
||||||
|
pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8,
|
||||||
|
pib_attribute: PibId::RxOnWhenIdle,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
|
|
||||||
|
let tx_queue = [
|
||||||
|
make_static!([0u8; 127]),
|
||||||
|
make_static!([0u8; 127]),
|
||||||
|
make_static!([0u8; 127]),
|
||||||
|
make_static!([0u8; 127]),
|
||||||
|
make_static!([0u8; 127]),
|
||||||
|
];
|
||||||
|
|
||||||
|
let runner = make_static!(Runner::new(mbox.mac_subsystem, tx_queue));
|
||||||
|
|
||||||
|
spawner.spawn(run_mac(runner)).unwrap();
|
||||||
|
|
||||||
|
let (driver, control) = mac::new(runner).await;
|
||||||
|
|
||||||
|
let _ = driver;
|
||||||
|
let _ = control;
|
||||||
|
}
|
@ -75,10 +75,7 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
|
||||||
defmt::info!("{:#x}", evt.mac_event());
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("setting extended address");
|
info!("setting extended address");
|
||||||
let extended_address: u64 = 0xACDE480000000002;
|
let extended_address: u64 = 0xACDE480000000002;
|
||||||
@ -89,10 +86,7 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
|
||||||
defmt::info!("{:#x}", evt.mac_event());
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("getting extended address");
|
info!("getting extended address");
|
||||||
mbox.mac_subsystem
|
mbox.mac_subsystem
|
||||||
@ -104,10 +98,10 @@ async fn main(spawner: Spawner) {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
{
|
{
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
let evt = mbox.mac_subsystem.read().await.unwrap();
|
||||||
info!("{:#x}", evt.mac_event());
|
info!("{:#x}", evt);
|
||||||
|
|
||||||
if let Ok(MacEvent::MlmeGetCnf(evt)) = evt.mac_event() {
|
if let MacEvent::MlmeGetCnf(evt) = evt {
|
||||||
if evt.pib_attribute_value_len == 8 {
|
if evt.pib_attribute_value_len == 8 {
|
||||||
let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) };
|
let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) };
|
||||||
|
|
||||||
@ -132,10 +126,10 @@ async fn main(spawner: Spawner) {
|
|||||||
info!("{}", a);
|
info!("{}", a);
|
||||||
mbox.mac_subsystem.send_command(&a).await.unwrap();
|
mbox.mac_subsystem.send_command(&a).await.unwrap();
|
||||||
let short_addr = {
|
let short_addr = {
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
let evt = mbox.mac_subsystem.read().await.unwrap();
|
||||||
info!("{:#x}", evt.mac_event());
|
info!("{:#x}", evt);
|
||||||
|
|
||||||
if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt.mac_event() {
|
if let MacEvent::MlmeAssociateCnf(conf) = evt {
|
||||||
conf.assoc_short_address
|
conf.assoc_short_address
|
||||||
} else {
|
} else {
|
||||||
defmt::panic!()
|
defmt::panic!()
|
||||||
@ -151,8 +145,8 @@ async fn main(spawner: Spawner) {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
{
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
let evt = mbox.mac_subsystem.read().await.unwrap();
|
||||||
info!("{:#x}", evt.mac_event());
|
info!("{:#x}", evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("sending data");
|
info!("sending data");
|
||||||
@ -175,12 +169,14 @@ async fn main(spawner: Spawner) {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
{
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
let evt = mbox.mac_subsystem.read().await.unwrap();
|
||||||
info!("{:#x}", evt.mac_event());
|
info!("{:#x}", evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
match mbox.mac_subsystem.read().await {
|
||||||
info!("{:#x}", evt.mac_event());
|
Ok(evt) => info!("{:#x}", evt),
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,8 @@ async fn main(spawner: Spawner) {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
{
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
let evt = mbox.mac_subsystem.read().await.unwrap();
|
||||||
info!("{:#x}", evt.mac_event());
|
info!("{:#x}", evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("setting extended address");
|
info!("setting extended address");
|
||||||
@ -70,8 +70,8 @@ async fn main(spawner: Spawner) {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
{
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
let evt = mbox.mac_subsystem.read().await.unwrap();
|
||||||
info!("{:#x}", evt.mac_event());
|
info!("{:#x}", evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("getting extended address");
|
info!("getting extended address");
|
||||||
@ -82,11 +82,12 @@ async fn main(spawner: Spawner) {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
{
|
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
|
||||||
info!("{:#x}", evt.mac_event());
|
|
||||||
|
|
||||||
if let Ok(MacEvent::MlmeGetCnf(evt)) = evt.mac_event() {
|
{
|
||||||
|
let evt = mbox.mac_subsystem.read().await.unwrap();
|
||||||
|
info!("{:#x}", evt);
|
||||||
|
|
||||||
|
if let MacEvent::MlmeGetCnf(evt) = evt {
|
||||||
if evt.pib_attribute_value_len == 8 {
|
if evt.pib_attribute_value_len == 8 {
|
||||||
let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) };
|
let value = unsafe { core::ptr::read_unaligned(evt.pib_attribute_value_ptr as *const u64) };
|
||||||
|
|
||||||
@ -110,10 +111,13 @@ async fn main(spawner: Spawner) {
|
|||||||
};
|
};
|
||||||
info!("{}", a);
|
info!("{}", a);
|
||||||
mbox.mac_subsystem.send_command(&a).await.unwrap();
|
mbox.mac_subsystem.send_command(&a).await.unwrap();
|
||||||
{
|
let short_addr = if let MacEvent::MlmeAssociateCnf(conf) = mbox.mac_subsystem.read().await.unwrap() {
|
||||||
let evt = mbox.mac_subsystem.read().await;
|
conf.assoc_short_address
|
||||||
info!("{:#x}", evt.mac_event());
|
} else {
|
||||||
}
|
defmt::panic!()
|
||||||
|
};
|
||||||
|
|
||||||
|
info!("{}", short_addr);
|
||||||
|
|
||||||
info!("Test OK");
|
info!("Test OK");
|
||||||
cortex_m::asm::bkpt();
|
cortex_m::asm::bkpt();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user