mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-25 16:23:10 +00:00
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.
|
||||
Ip,
|
||||
|
||||
/// IEEE 802_15_4 medium
|
||||
Ieee802154,
|
||||
}
|
||||
|
||||
impl Default for Medium {
|
||||
|
@ -37,6 +37,7 @@ proto-ipv4 = ["smoltcp/proto-ipv4"]
|
||||
proto-ipv6 = ["smoltcp/proto-ipv6"]
|
||||
medium-ethernet = ["smoltcp/medium-ethernet"]
|
||||
medium-ip = ["smoltcp/medium-ip"]
|
||||
medium-ieee802154 = ["smoltcp/medium-ieee802154"]
|
||||
igmp = ["smoltcp/proto-igmp"]
|
||||
|
||||
[dependencies]
|
||||
|
@ -51,6 +51,8 @@ where
|
||||
Medium::Ethernet => phy::Medium::Ethernet,
|
||||
#[cfg(feature = "medium-ip")]
|
||||
Medium::Ip => phy::Medium::Ip,
|
||||
#[cfg(feature = "medium-ieee802154")]
|
||||
Medium::Ieee802154 => phy::Medium::Ieee802154,
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => panic!(
|
||||
"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_time::{Instant, Timer};
|
||||
use futures::pin_mut;
|
||||
#[allow(unused_imports)]
|
||||
use heapless::Vec;
|
||||
#[cfg(feature = "igmp")]
|
||||
pub use smoltcp::iface::MulticastError;
|
||||
#[allow(unused_imports)]
|
||||
use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage};
|
||||
#[cfg(feature = "dhcpv4")]
|
||||
use smoltcp::socket::dhcpv4::{self, RetryConfig};
|
||||
@ -34,6 +36,8 @@ use smoltcp::socket::dhcpv4::{self, RetryConfig};
|
||||
pub use smoltcp::wire::IpListenEndpoint;
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
pub use smoltcp::wire::{EthernetAddress, HardwareAddress};
|
||||
#[cfg(feature = "medium-ieee802154")]
|
||||
pub use smoltcp::wire::{HardwareAddress, Ieee802154Address};
|
||||
pub use smoltcp::wire::{IpAddress, IpCidr, IpEndpoint};
|
||||
#[cfg(feature = "proto-ipv4")]
|
||||
pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr};
|
||||
@ -232,7 +236,7 @@ impl<D: Driver + 'static> Stack<D> {
|
||||
resources: &'static mut StackResources<SOCK>,
|
||||
random_seed: u64,
|
||||
) -> Self {
|
||||
#[cfg(feature = "medium-ethernet")]
|
||||
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
|
||||
let medium = device.capabilities().medium;
|
||||
|
||||
let hardware_addr = match medium {
|
||||
@ -240,6 +244,8 @@ impl<D: Driver + 'static> Stack<D> {
|
||||
Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress(device.ethernet_address())),
|
||||
#[cfg(feature = "medium-ip")]
|
||||
Medium::Ip => HardwareAddress::Ip,
|
||||
#[cfg(feature = "medium-ieee802154")]
|
||||
Medium::Ieee802154 => HardwareAddress::Ieee802154(Ieee802154Address::Absent),
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => panic!(
|
||||
"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;
|
||||
|
||||
#[cfg_attr(feature = "medium-ieee802154", allow(unused_mut))]
|
||||
let mut socket = SocketStack {
|
||||
sockets,
|
||||
iface,
|
||||
@ -269,6 +276,7 @@ impl<D: Driver + 'static> Stack<D> {
|
||||
next_local_port,
|
||||
};
|
||||
|
||||
#[cfg_attr(feature = "medium-ieee802154", allow(unused_mut))]
|
||||
let mut inner = Inner {
|
||||
device,
|
||||
link_up: false,
|
||||
@ -287,6 +295,9 @@ impl<D: Driver + 'static> Stack<D> {
|
||||
dns_waker: WakerRegistration::new(),
|
||||
};
|
||||
|
||||
#[cfg(feature = "medium-ieee802154")]
|
||||
let _ = config;
|
||||
|
||||
#[cfg(feature = "proto-ipv4")]
|
||||
match config.ipv4 {
|
||||
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-hal-common = { version = "0.1.0", path = "../embassy-hal-common" }
|
||||
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 }
|
||||
cortex-m = "0.7.6"
|
||||
@ -26,13 +27,14 @@ aligned = "0.4.1"
|
||||
bit_field = "0.10.2"
|
||||
stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] }
|
||||
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 }
|
||||
|
||||
[features]
|
||||
defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"]
|
||||
|
||||
ble = ["dep:stm32wb-hci"]
|
||||
mac = ["dep:bitflags"]
|
||||
mac = ["dep:bitflags", "dep:embassy-net-driver" ]
|
||||
|
||||
stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ]
|
||||
stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ]
|
||||
|
@ -1,5 +1,6 @@
|
||||
#![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.
|
||||
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::{
|
||||
AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication,
|
||||
@ -8,9 +8,9 @@ use super::responses::{
|
||||
AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm,
|
||||
PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm,
|
||||
};
|
||||
use crate::evt::EvtBox;
|
||||
use crate::evt::{EvtBox, MemoryManager};
|
||||
use crate::mac::opcodes::OpcodeM0ToM4;
|
||||
use crate::sub::mac::Mac;
|
||||
use crate::sub::mac::{self, Mac};
|
||||
|
||||
pub(crate) trait ParseableMacEvent: Sized {
|
||||
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))]
|
||||
#[derive(Debug)]
|
||||
pub enum MacEvent<'a> {
|
||||
MlmeAssociateCnf(&'a AssociateConfirm),
|
||||
MlmeDisassociateCnf(&'a DisassociateConfirm),
|
||||
@ -102,3 +51,103 @@ pub enum MacEvent<'a> {
|
||||
McpsDataInd(&'a DataIndication),
|
||||
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
|
||||
/// to indicate the reception of an association request command
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct AssociateIndication {
|
||||
/// Extended address of the device requesting association
|
||||
@ -31,6 +32,7 @@ impl ParseableMacEvent for AssociateIndication {}
|
||||
/// MLME DISASSOCIATE indication which will be used to send
|
||||
/// disassociation indication to the application.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct DisassociateIndication {
|
||||
/// 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
|
||||
/// within a beacon frame received by the MAC to the application
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct BeaconNotifyIndication {
|
||||
/// 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
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct CommStatusIndication {
|
||||
/// 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
|
||||
/// previously allocated GTS has been deallocated
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct GtsIndication {
|
||||
/// 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
|
||||
/// application of the presence of an orphaned device
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct OrphanIndication {
|
||||
/// 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
|
||||
/// of synchronization with the coordinator
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct SyncLossIndication {
|
||||
/// 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
|
||||
/// and the resetting of the DPS values in the PHY
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct DpsIndication {
|
||||
/// byte stuffing to keep 32 bit alignment
|
||||
@ -181,6 +189,7 @@ pub struct DpsIndication {
|
||||
impl ParseableMacEvent for DpsIndication {}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct DataIndication {
|
||||
/// Pointer to the set of octets forming the MSDU being indicated
|
||||
@ -236,14 +245,15 @@ pub struct DataIndication {
|
||||
impl ParseableMacEvent for DataIndication {}
|
||||
|
||||
impl DataIndication {
|
||||
pub fn payload<'a>(&'a self) -> &'a [u8] {
|
||||
unsafe { slice::from_raw_parts(self.msdu_ptr, self.msdu_length as usize) }
|
||||
pub fn payload<'a>(&'a self) -> &'a mut [u8] {
|
||||
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
|
||||
/// reception to upper layer as defined in Zigbee r22 - D.8.2
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct PollIndication {
|
||||
/// addressing mode used
|
||||
|
@ -1,8 +1,21 @@
|
||||
pub mod commands;
|
||||
mod consts;
|
||||
pub mod control;
|
||||
mod driver;
|
||||
pub mod event;
|
||||
pub mod indications;
|
||||
mod macros;
|
||||
mod opcodes;
|
||||
pub mod responses;
|
||||
pub mod runner;
|
||||
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
|
||||
/// its request to associate was successful or unsuccessful
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct AssociateConfirm {
|
||||
/// 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.
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct DisassociateConfirm {
|
||||
/// status of the disassociation attempt
|
||||
@ -46,6 +48,7 @@ impl ParseableMacEvent for DisassociateConfirm {}
|
||||
|
||||
/// MLME GET Confirm which requests information about a given PIB attribute
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct GetConfirm {
|
||||
/// 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
|
||||
/// or to deallocate an existing GTS
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct GtsConfirm {
|
||||
/// 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
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct ResetConfirm {
|
||||
/// The result of the reset operation
|
||||
status: MacStatus,
|
||||
pub status: MacStatus,
|
||||
/// byte stuffing to keep 32 bit alignment
|
||||
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
|
||||
/// to enable or disable the receiver
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct RxEnableConfirm {
|
||||
/// Result of the request to enable or disable the receiver
|
||||
status: MacStatus,
|
||||
pub status: MacStatus,
|
||||
/// byte stuffing to keep 32 bit alignment
|
||||
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
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct ScanConfirm {
|
||||
/// 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
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct SetConfirm {
|
||||
/// 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
|
||||
/// start using a new superframe configuration
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct StartConfirm {
|
||||
/// 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
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct PollConfirm {
|
||||
/// 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
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct DpsConfirm {
|
||||
/// 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
|
||||
/// channel sounding information
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct SoundingConfirm {
|
||||
/// Results of the sounding measurement
|
||||
sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED],
|
||||
pub sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED],
|
||||
|
||||
status: u8,
|
||||
}
|
||||
@ -195,6 +207,7 @@ impl ParseableMacEvent for SoundingConfirm {}
|
||||
/// MLME CALIBRATE Confirm which reports the result of a request to the PHY
|
||||
/// to provide internal propagation path information
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct CalibrateConfirm {
|
||||
/// 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
|
||||
/// MAC data related requests from the application
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct DataConfirm {
|
||||
/// 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
|
||||
/// the status of its request to purge an MSDU from the transaction queue
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct PurgeConfirm {
|
||||
/// 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;
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -37,7 +39,7 @@ numeric_enum! {
|
||||
numeric_enum! {
|
||||
#[repr(u8)]
|
||||
/// this enum contains all the MAC PIB Ids
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum PibId {
|
||||
// PHY
|
||||
@ -96,7 +98,7 @@ numeric_enum! {
|
||||
|
||||
numeric_enum! {
|
||||
#[repr(u8)]
|
||||
#[derive(Default, Clone, Copy)]
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum AddressMode {
|
||||
#[default]
|
||||
@ -113,6 +115,18 @@ pub union MacAddress {
|
||||
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")]
|
||||
impl defmt::Format for MacAddress {
|
||||
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
|
||||
/// which the beacon is received
|
||||
#[derive(Default, Clone, Copy)]
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct PanDescriptor {
|
||||
/// PAN identifier of the coordinator
|
||||
@ -223,7 +237,7 @@ impl TryFrom<&[u8]> for PanDescriptor {
|
||||
|
||||
numeric_enum! {
|
||||
#[repr(u8)]
|
||||
#[derive(Default, Clone, Copy)]
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Building wireless applications with STM32WB series MCUs - Application note 13.10.3
|
||||
pub enum MacChannel {
|
||||
@ -289,7 +303,7 @@ defmt::bitflags! {
|
||||
|
||||
numeric_enum! {
|
||||
#[repr(u8)]
|
||||
#[derive(Default, Clone, Copy)]
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum KeyIdMode {
|
||||
#[default]
|
||||
@ -306,6 +320,7 @@ numeric_enum! {
|
||||
|
||||
numeric_enum! {
|
||||
#[repr(u8)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum AssociationStatus {
|
||||
/// Association successful
|
||||
@ -319,7 +334,7 @@ numeric_enum! {
|
||||
|
||||
numeric_enum! {
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum DisassociationReason {
|
||||
/// The coordinator wishes the device to leave the PAN.
|
||||
@ -331,7 +346,7 @@ numeric_enum! {
|
||||
|
||||
numeric_enum! {
|
||||
#[repr(u8)]
|
||||
#[derive(Default, Clone, Copy)]
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum SecurityLevel {
|
||||
/// MAC Unsecured Mode Security
|
||||
@ -346,6 +361,7 @@ numeric_enum! {
|
||||
|
||||
numeric_enum! {
|
||||
#[repr(u8)]
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum ScanType {
|
||||
EdScan = 0x00,
|
||||
@ -356,7 +372,7 @@ numeric_enum! {
|
||||
}
|
||||
|
||||
/// newtype for Pan Id
|
||||
#[derive(Default, Clone, Copy)]
|
||||
#[derive(Default, Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct PanId(pub [u8; 2]);
|
||||
|
||||
|
@ -12,7 +12,7 @@ use crate::cmd::CmdPacket;
|
||||
use crate::consts::TlPacketType;
|
||||
use crate::evt::{EvtBox, EvtPacket};
|
||||
use crate::mac::commands::MacCommand;
|
||||
use crate::mac::event::Event;
|
||||
use crate::mac::event::MacEvent;
|
||||
use crate::mac::typedefs::MacError;
|
||||
use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER};
|
||||
use crate::{channels, evt};
|
||||
@ -94,14 +94,16 @@ impl Mac {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn read(&self) -> Event {
|
||||
Event::new(self.tl_read().await)
|
||||
pub async fn read(&self) -> Result<MacEvent<'_>, ()> {
|
||||
MacEvent::new(self.tl_read().await)
|
||||
}
|
||||
}
|
||||
|
||||
impl evt::MemoryManager for Mac {
|
||||
/// SAFETY: passing a pointer to something other than a managed event packet is UB
|
||||
unsafe fn drop_event_packet(_: *mut EvtPacket) {
|
||||
trace!("mac drop event");
|
||||
|
||||
// Write the ack
|
||||
CmdPacket::write_into(
|
||||
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
|
||||
let _ = poll_once(Ipcc::receive::<bool>(
|
||||
let _ = poll_once(Ipcc::receive::<()>(
|
||||
channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL,
|
||||
|| 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>> {
|
||||
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
|
||||
@ -401,6 +413,16 @@ where
|
||||
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.
|
||||
pub fn sender(&self) -> Sender<'_, M, T, N> {
|
||||
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-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-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "udp", "medium-ieee802154", "nightly"], optional=true }
|
||||
|
||||
defmt = "0.3"
|
||||
defmt-rtt = "0.4"
|
||||
@ -20,11 +21,11 @@ embedded-hal = "0.2.6"
|
||||
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||
futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
|
||||
heapless = { version = "0.7.5", default-features = false }
|
||||
|
||||
static_cell = { version = "1.1", features = ["nightly"]}
|
||||
|
||||
[features]
|
||||
default = ["ble", "mac"]
|
||||
mac = ["embassy-stm32-wpan/mac"]
|
||||
mac = ["embassy-stm32-wpan/mac", "dep:embassy-net"]
|
||||
ble = ["embassy-stm32-wpan/ble"]
|
||||
|
||||
[[bin]]
|
||||
@ -39,6 +40,10 @@ required-features = ["mac"]
|
||||
name = "mac_ffd"
|
||||
required-features = ["mac"]
|
||||
|
||||
[[bin]]
|
||||
name = "mac_ffd_net"
|
||||
required-features = ["mac"]
|
||||
|
||||
[[bin]]
|
||||
name = "eddystone_beacon"
|
||||
required-features = ["ble"]
|
||||
|
@ -73,10 +73,7 @@ async fn main(spawner: Spawner) {
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
defmt::info!("{:#x}", evt.mac_event());
|
||||
}
|
||||
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||
|
||||
info!("setting extended address");
|
||||
let extended_address: u64 = 0xACDE480000000001;
|
||||
@ -87,10 +84,7 @@ async fn main(spawner: Spawner) {
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
defmt::info!("{:#x}", evt.mac_event());
|
||||
}
|
||||
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||
|
||||
info!("setting short address");
|
||||
let short_address: u16 = 0x1122;
|
||||
@ -101,10 +95,7 @@ async fn main(spawner: Spawner) {
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
defmt::info!("{:#x}", evt.mac_event());
|
||||
}
|
||||
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||
|
||||
info!("setting association permit");
|
||||
let association_permit: bool = true;
|
||||
@ -115,10 +106,7 @@ async fn main(spawner: Spawner) {
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
defmt::info!("{:#x}", evt.mac_event());
|
||||
}
|
||||
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||
|
||||
info!("setting TX power");
|
||||
let transmit_power: i8 = 2;
|
||||
@ -129,10 +117,7 @@ async fn main(spawner: Spawner) {
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
defmt::info!("{:#x}", evt.mac_event());
|
||||
}
|
||||
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||
|
||||
info!("starting FFD device");
|
||||
mbox.mac_subsystem
|
||||
@ -147,10 +132,7 @@ async fn main(spawner: Spawner) {
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
defmt::info!("{:#x}", evt.mac_event());
|
||||
}
|
||||
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||
|
||||
info!("setting RX on when idle");
|
||||
let rx_on_while_idle: bool = true;
|
||||
@ -161,14 +143,11 @@ async fn main(spawner: Spawner) {
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
defmt::info!("{:#x}", evt.mac_event());
|
||||
}
|
||||
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||
|
||||
loop {
|
||||
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!("{:#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
|
||||
.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
defmt::info!("{:#x}", evt.mac_event());
|
||||
}
|
||||
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||
|
||||
info!("setting extended address");
|
||||
let extended_address: u64 = 0xACDE480000000002;
|
||||
@ -89,10 +86,7 @@ async fn main(spawner: Spawner) {
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
defmt::info!("{:#x}", evt.mac_event());
|
||||
}
|
||||
defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap());
|
||||
|
||||
info!("getting extended address");
|
||||
mbox.mac_subsystem
|
||||
@ -104,10 +98,10 @@ async fn main(spawner: Spawner) {
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
info!("{:#x}", evt.mac_event());
|
||||
let evt = mbox.mac_subsystem.read().await.unwrap();
|
||||
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 {
|
||||
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);
|
||||
mbox.mac_subsystem.send_command(&a).await.unwrap();
|
||||
let short_addr = {
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
info!("{:#x}", evt.mac_event());
|
||||
let evt = mbox.mac_subsystem.read().await.unwrap();
|
||||
info!("{:#x}", evt);
|
||||
|
||||
if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt.mac_event() {
|
||||
if let MacEvent::MlmeAssociateCnf(conf) = evt {
|
||||
conf.assoc_short_address
|
||||
} else {
|
||||
defmt::panic!()
|
||||
@ -151,8 +145,8 @@ async fn main(spawner: Spawner) {
|
||||
.await
|
||||
.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
info!("{:#x}", evt.mac_event());
|
||||
let evt = mbox.mac_subsystem.read().await.unwrap();
|
||||
info!("{:#x}", evt);
|
||||
}
|
||||
|
||||
info!("sending data");
|
||||
@ -175,12 +169,14 @@ async fn main(spawner: Spawner) {
|
||||
.await
|
||||
.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
info!("{:#x}", evt.mac_event());
|
||||
let evt = mbox.mac_subsystem.read().await.unwrap();
|
||||
info!("{:#x}", evt);
|
||||
}
|
||||
|
||||
loop {
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
info!("{:#x}", evt.mac_event());
|
||||
match mbox.mac_subsystem.read().await {
|
||||
Ok(evt) => info!("{:#x}", evt),
|
||||
_ => continue,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -56,8 +56,8 @@ async fn main(spawner: Spawner) {
|
||||
.await
|
||||
.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
info!("{:#x}", evt.mac_event());
|
||||
let evt = mbox.mac_subsystem.read().await.unwrap();
|
||||
info!("{:#x}", evt);
|
||||
}
|
||||
|
||||
info!("setting extended address");
|
||||
@ -70,8 +70,8 @@ async fn main(spawner: Spawner) {
|
||||
.await
|
||||
.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
info!("{:#x}", evt.mac_event());
|
||||
let evt = mbox.mac_subsystem.read().await.unwrap();
|
||||
info!("{:#x}", evt);
|
||||
}
|
||||
|
||||
info!("getting extended address");
|
||||
@ -82,11 +82,12 @@ async fn main(spawner: Spawner) {
|
||||
})
|
||||
.await
|
||||
.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 {
|
||||
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);
|
||||
mbox.mac_subsystem.send_command(&a).await.unwrap();
|
||||
{
|
||||
let evt = mbox.mac_subsystem.read().await;
|
||||
info!("{:#x}", evt.mac_event());
|
||||
}
|
||||
let short_addr = if let MacEvent::MlmeAssociateCnf(conf) = mbox.mac_subsystem.read().await.unwrap() {
|
||||
conf.assoc_short_address
|
||||
} else {
|
||||
defmt::panic!()
|
||||
};
|
||||
|
||||
info!("{}", short_addr);
|
||||
|
||||
info!("Test OK");
|
||||
cortex_m::asm::bkpt();
|
||||
|
Loading…
Reference in New Issue
Block a user