From 4aca7c8811b70e420280893784cdad2acbe326f9 Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 10 Jul 2023 16:54:48 +0100 Subject: [PATCH 01/13] wip --- embassy-stm32-wpan/Cargo.toml | 1 + embassy-stm32-wpan/src/sub/mac/commands.rs | 83 +++++++++++++ .../src/sub/{mac.rs => mac/mod.rs} | 18 +++ embassy-stm32-wpan/src/sub/mac/opcodes.rs | 27 ++++ examples/stm32wb/.cargo/config.toml | 4 +- examples/stm32wb/Cargo.toml | 6 +- examples/stm32wb/src/bin/tl_mbox_mac_2.rs | 117 ++++++++++++++++++ rust-toolchain.toml | 4 +- 8 files changed, 255 insertions(+), 5 deletions(-) create mode 100644 embassy-stm32-wpan/src/sub/mac/commands.rs rename embassy-stm32-wpan/src/sub/{mac.rs => mac/mod.rs} (88%) create mode 100644 embassy-stm32-wpan/src/sub/mac/opcodes.rs create mode 100644 examples/stm32wb/src/bin/tl_mbox_mac_2.rs diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 5141f9bd2..4b5dcdd29 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -28,6 +28,7 @@ stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } stm32wb-hci = { version = "0.1.2", features = ["version-5-0"], optional = true } [features] +default = ["stm32wb55rg", "mac", "ble"] defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] ble = ["dep:stm32wb-hci"] diff --git a/embassy-stm32-wpan/src/sub/mac/commands.rs b/embassy-stm32-wpan/src/sub/mac/commands.rs new file mode 100644 index 000000000..75a31d2fc --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/commands.rs @@ -0,0 +1,83 @@ +use bit_field::BitField; + +use super::opcodes::OpcodeM4ToM0; + +pub trait MacCommand { + type Response; + const OPCODE: OpcodeM4ToM0; + const SIZE: usize; + + fn copy_into_slice(&self, buf: &mut [u8]); +} + +pub struct ResetRequest { + /// MAC PIB attributes are set to their default values or not during reset + pub set_default_pib: bool, +} + +impl MacCommand for ResetRequest { + type Response = (); + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeResetReq; + const SIZE: usize = 4; + + fn copy_into_slice(&self, buf: &mut [u8]) { + buf[0] = self.set_default_pib as u8; + } +} + +#[repr(C)] +pub struct SetRequest { + pub pib_attribute_ptr: *const u8, + pub pib_attribute: u8, + pub stuffing: [u8; 3], +} + +impl MacCommand for SetRequest { + type Response = (); + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSetReq; + const SIZE: usize = 8; + + fn copy_into_slice(&self, buf: &mut [u8]) { + let address = self.pib_attribute_ptr as usize; + + // 68 ff 2 20 6f + + let a = unsafe { core::slice::from_raw_parts(&self as *const _ as *const u8, Self::SIZE) }; + debug!("{:#04x}", a); + + unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, 8) }; + + // buf[0] = self.pib_attribute_ptr as u8; + // buf[1] = self.pib_attribute; + } +} + +pub struct AssociateRequest { + pub channel_number: u8, + pub channel_page: u8, + pub coord_addr_mode: u8, + pub capability_information: u8, + pub coord_pan_id: [u8; 2], + pub security_level: u8, + pub key_id_mode: u8, + pub key_source: [u8; 8], + pub coord_address: MacAddress, + pub key_index: u8, +} + +impl MacCommand for AssociateRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateReq; + const SIZE: usize = 25; + type Response = (); + + fn copy_into_slice(&self, buf: &mut [u8]) { + let a = unsafe { core::slice::from_raw_parts(&self as *const _ as *const u8, core::mem::size_of::()) }; + + buf[..a.len()].copy_from_slice(a); + } +} + +pub union MacAddress { + pub short: [u8; 2], + pub extended: [u8; 8], +} diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs similarity index 88% rename from embassy-stm32-wpan/src/sub/mac.rs rename to embassy-stm32-wpan/src/sub/mac/mod.rs index f7a59b0e4..83970a881 100644 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -8,12 +8,16 @@ use embassy_futures::poll_once; use embassy_stm32::ipcc::Ipcc; use embassy_sync::waitqueue::AtomicWaker; +use self::commands::MacCommand; use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::{EvtBox, EvtPacket}; use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; use crate::{channels, evt}; +pub mod commands; +mod opcodes; + static MAC_WAKER: AtomicWaker = AtomicWaker::new(); static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false); @@ -77,8 +81,22 @@ impl Mac { }) .await; } + + pub async fn send_command(&self, cmd: T) -> u8 + where + T: MacCommand, + { + let mut payload = [0u8; MAX_PACKET_SIZE]; + cmd.copy_into_slice(&mut payload); + + debug!("sending {:#x}", payload[..T::SIZE]); + + self.write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]).await + } } +const MAX_PACKET_SIZE: usize = 255; + 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) { diff --git a/embassy-stm32-wpan/src/sub/mac/opcodes.rs b/embassy-stm32-wpan/src/sub/mac/opcodes.rs new file mode 100644 index 000000000..511b78157 --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/opcodes.rs @@ -0,0 +1,27 @@ +const ST_VENDOR_OGF: u16 = 0x3F; +const MAC_802_15_4_CMD_OPCODE_OFFSET: u16 = 0x280; + +const fn opcode(ocf: u16) -> isize { + ((ST_VENDOR_OGF << 9) | (MAC_802_15_4_CMD_OPCODE_OFFSET + ocf)) as isize +} + +pub enum OpcodeM4ToM0 { + MlmeAssociateReq = opcode(0x00), + MlmeAssociateRes = opcode(0x01), + MlmeDisassociateReq = opcode(0x02), + MlmeGetReq = opcode(0x03), + MlmeGtsReq = opcode(0x04), + MlmeOrphanRes = opcode(0x05), + MlmeResetReq = opcode(0x06), + MlmeRxEnableReq = opcode(0x07), + MlmeScanReq = opcode(0x08), + MlmeSetReq = opcode(0x09), + MlmeStartReq = opcode(0x0A), + MlmeSyncReq = opcode(0x0B), + MlmePollReq = opcode(0x0C), + MlmeDpsReq = opcode(0x0D), + MlmeSoundingReq = opcode(0x0E), + MlmeCalibrateReq = opcode(0x0F), + McpsDataReq = opcode(0x10), + McpsPurgeReq = opcode(0x11), +} diff --git a/examples/stm32wb/.cargo/config.toml b/examples/stm32wb/.cargo/config.toml index 8b6d6d754..cf62a10a0 100644 --- a/examples/stm32wb/.cargo/config.toml +++ b/examples/stm32wb/.cargo/config.toml @@ -1,7 +1,7 @@ [target.'cfg(all(target_arch = "arm", target_os = "none"))'] # replace STM32WB55CCUx with your chip as listed in `probe-rs chip list` -# runner = "probe-rs run --chip STM32WB55RGVx --speed 1000 --connect-under-reset" -runner = "teleprobe local run --chip STM32WB55RG --elf" +runner = "probe-run --chip STM32WB55RGVx --speed 1000 --connect-under-reset" +# runner = "teleprobe local run --chip STM32WB55RG --elf" [build] target = "thumbv7em-none-eabihf" diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 203ca1486..109734546 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -23,7 +23,7 @@ heapless = { version = "0.7.5", default-features = false } [features] -default = ["ble"] +default = ["ble", "mac"] mac = ["embassy-stm32-wpan/mac"] ble = ["embassy-stm32-wpan/ble"] @@ -35,6 +35,10 @@ required-features = ["ble"] name = "tl_mbox_mac" required-features = ["mac"] +[[bin]] +name = "tl_mbox_mac_2" +required-features = ["mac"] + [[bin]] name = "eddystone_beacon" required-features = ["ble"] diff --git a/examples/stm32wb/src/bin/tl_mbox_mac_2.rs b/examples/stm32wb/src/bin/tl_mbox_mac_2.rs new file mode 100644 index 000000000..e069adf87 --- /dev/null +++ b/examples/stm32wb/src/bin/tl_mbox_mac_2.rs @@ -0,0 +1,117 @@ +#![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::sub::mac::commands::{AssociateRequest, MacAddress, ResetRequest, SetRequest}; +use embassy_stm32_wpan::sub::mm; +use embassy_stm32_wpan::TlMbox; +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::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"); + let response = mbox + .mac_subsystem + .send_command(ResetRequest { set_default_pib: true }) + .await; + info!("{}", response); + + info!("setting extended address"); + let extended_address: u64 = 0xACDE480000000001; + defmt::debug!("{}", &extended_address as *const _ as *const u8); + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &extended_address as *const _ as *const u8, + pib_attribute: 0x6F, + stuffing: [0; 3], + }) + .await; + info!("{}", response); + + // info!("association request"); + // mbox.mac_subsystem + // .send_command(AssociateRequest { + // channel_number: 16, + // channel_page: 0, + // coord_addr_mode: 2, + // coord_address: MacAddress { short: [0x22, 0x11] }, + // capability_information: 0x80, + // coord_pan_id: [0xAA, 0x1A], + // security_level: 0, + + // key_id_mode: 0, + // key_index: 0, + // key_source: [0; 8], + // }) + // .await; + // info!("reading"); + // let result = mbox.mac_subsystem.read().await; + // info!("{}", result.payload()); + + // + // info!("starting ble..."); + // mbox.ble_subsystem.t_write(0x0c, &[]).await; + // + // info!("waiting for ble..."); + // let ble_event = mbox.ble_subsystem.tl_read().await; + // + // info!("ble event: {}", ble_event.payload()); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 5db74c7a9..bad6d3a42 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,8 +1,8 @@ # Before upgrading check that everything is available on all tier1 targets here: # https://rust-lang.github.io/rustup-components-history [toolchain] -channel = "nightly-2023-06-28" -components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] +channel = "nightly" +components = [ "rust-src", "rustfmt", "llvm-tools" ] targets = [ "thumbv7em-none-eabi", "thumbv7m-none-eabi", From 6f4172fbc1280fdd9190ccddcf3cf6f25788c7be Mon Sep 17 00:00:00 2001 From: goueslati Date: Tue, 11 Jul 2023 16:07:33 +0100 Subject: [PATCH 02/13] wip: added MAC commands --- embassy-stm32-wpan/src/consts.rs | 2 + embassy-stm32-wpan/src/sub/mac/commands.rs | 426 +++++++++++++++--- embassy-stm32-wpan/src/sub/mac/mod.rs | 45 +- embassy-stm32-wpan/src/sub/mac/responses.rs | 0 embassy-stm32-wpan/src/sub/mac/typedefs.rs | 97 ++++ examples/stm32wb/Cargo.toml | 2 +- examples/stm32wb/src/bin/mac_ffd.rs | 174 +++++++ .../src/bin/{tl_mbox_mac_2.rs => mac_rfd.rs} | 63 ++- 8 files changed, 718 insertions(+), 91 deletions(-) create mode 100644 embassy-stm32-wpan/src/sub/mac/responses.rs create mode 100644 embassy-stm32-wpan/src/sub/mac/typedefs.rs create mode 100644 examples/stm32wb/src/bin/mac_ffd.rs rename examples/stm32wb/src/bin/{tl_mbox_mac_2.rs => mac_rfd.rs} (72%) diff --git a/embassy-stm32-wpan/src/consts.rs b/embassy-stm32-wpan/src/consts.rs index 1c84addb1..bd70851ea 100644 --- a/embassy-stm32-wpan/src/consts.rs +++ b/embassy-stm32-wpan/src/consts.rs @@ -6,6 +6,8 @@ use crate::PacketHeader; #[derive(Debug)] #[repr(C)] pub enum TlPacketType { + MacCmd = 0x00, + BleCmd = 0x01, AclData = 0x02, BleEvt = 0x04, diff --git a/embassy-stm32-wpan/src/sub/mac/commands.rs b/embassy-stm32-wpan/src/sub/mac/commands.rs index 75a31d2fc..3c234a3ce 100644 --- a/embassy-stm32-wpan/src/sub/mac/commands.rs +++ b/embassy-stm32-wpan/src/sub/mac/commands.rs @@ -1,13 +1,99 @@ -use bit_field::BitField; - use super::opcodes::OpcodeM4ToM0; +use super::typedefs::{AddressMode, GtsCharacteristics, MacAddress, PibId}; pub trait MacCommand { - type Response; const OPCODE: OpcodeM4ToM0; const SIZE: usize; - fn copy_into_slice(&self, buf: &mut [u8]); + fn copy_into_slice(&self, buf: &mut [u8]) { + unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, 8) }; + } +} + +/// MLME ASSOCIATE Request used to request an association +pub struct AssociateRequest { + /// the logical channel on which to attempt association + pub channel_number: u8, + /// the channel page on which to attempt association + pub channel_page: u8, + /// coordinator addressing mode + pub coord_addr_mode: AddressMode, + /// operational capabilities of the associating device + pub capability_information: u8, + /// the identifier of the PAN with which to associate + pub coord_pan_id: [u8; 2], + /// the security level to be used + pub security_level: u8, + /// the mode used to identify the key to be used + pub key_id_mode: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], + /// Coordinator address + pub coord_address: MacAddress, + /// the index of the key to be used + pub key_index: u8, +} + +impl MacCommand for AssociateRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateReq; + const SIZE: usize = 25; +} + +/// MLME DISASSOCIATE Request sed to request a disassociation +pub struct DisassociateRequest { + /// device addressing mode used + pub device_addr_mode: AddressMode, + /// the identifier of the PAN of the device + pub device_pan_id: [u8; 2], + /// the reason for the disassociation + pub disassociate_reason: u8, + /// device address + pub device_address: MacAddress, + /// `true` if the disassociation notification command is to be sent indirectly + pub tx_indirect: bool, + /// the security level to be used + pub security_level: u8, + /// the mode to be used to indetify the key to be used + pub key_id_mode: u8, + /// the index of the key to be used + pub key_index: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], +} + +impl MacCommand for DisassociateRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDisassociateReq; + const SIZE: usize = 24; +} + +/// MLME GET Request used to request a PIB value +pub struct GetRequest { + /// the name of the PIB attribute to read + pub pib_attribute: PibId, +} + +impl MacCommand for GetRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq; + const SIZE: usize = 4; +} + +/// MLME GTS Request used to request and maintain GTSs +pub struct GtsRequest { + /// the characteristics of the GTS + pub characteristics: GtsCharacteristics, + /// the security level to be used + pub security_level: u8, + /// the mode used to identify the key to be used + pub key_id_mode: u8, + /// the index of the key to be used + pub key_index: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], +} + +impl MacCommand for GtsRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeGetReq; + const SIZE: usize = 12; } pub struct ResetRequest { @@ -16,68 +102,302 @@ pub struct ResetRequest { } impl MacCommand for ResetRequest { - type Response = (); const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeResetReq; const SIZE: usize = 4; +} + +/// MLME RX ENABLE Request used to request that the receiver is either enabled +/// for a finite period of time or disabled +pub struct RxEnableRequest { + /// the request operation can be deferred or not + pub defer_permit: bool, + /// configure the transceiver to RX with ranging for a value of + /// RANGING_ON or to not enable ranging for RANGING_OFF + pub ranging_rx_control: u8, + /// number of symbols measured before the receiver is to be enabled or disabled + pub rx_on_time: [u8; 4], + /// number of symbols for which the receiver is to be enabled + pub rx_on_duration: [u8; 4], +} + +impl MacCommand for RxEnableRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeRxEnableReq; + const SIZE: usize = 12; fn copy_into_slice(&self, buf: &mut [u8]) { - buf[0] = self.set_default_pib as u8; + buf[0] = self.defer_permit as u8; + buf[1] = self.ranging_rx_control as u8; + + // stuffing to keep 32bit alignment + buf[2] = 0; + buf[3] = 0; + + buf[4..8].copy_from_slice(&self.rx_on_time); + buf[8..12].copy_from_slice(&self.rx_on_duration); } } -#[repr(C)] -pub struct SetRequest { - pub pib_attribute_ptr: *const u8, - pub pib_attribute: u8, - pub stuffing: [u8; 3], -} - -impl MacCommand for SetRequest { - type Response = (); - const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSetReq; - const SIZE: usize = 8; - - fn copy_into_slice(&self, buf: &mut [u8]) { - let address = self.pib_attribute_ptr as usize; - - // 68 ff 2 20 6f - - let a = unsafe { core::slice::from_raw_parts(&self as *const _ as *const u8, Self::SIZE) }; - debug!("{:#04x}", a); - - unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, 8) }; - - // buf[0] = self.pib_attribute_ptr as u8; - // buf[1] = self.pib_attribute; - } -} - -pub struct AssociateRequest { - pub channel_number: u8, +/// MLME SCAN Request used to initiate a channel scan over a given list of channels +pub struct ScanRequest { + /// the type of scan to be performed + pub scan_type: u8, + /// the time spent on scanning each channel + pub scan_duration: u8, + /// channel page on which to perform the scan pub channel_page: u8, - pub coord_addr_mode: u8, - pub capability_information: u8, - pub coord_pan_id: [u8; 2], + /// security level to be used pub security_level: u8, - pub key_id_mode: u8, + /// indicate which channels are to be scanned + pub scan_channels: [u8; 4], + /// originator the key to be used pub key_source: [u8; 8], - pub coord_address: MacAddress, + /// mode used to identify the key to be used + pub key_id_mode: u8, + /// index of the key to be used pub key_index: u8, } -impl MacCommand for AssociateRequest { - const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateReq; - const SIZE: usize = 25; - type Response = (); - - fn copy_into_slice(&self, buf: &mut [u8]) { - let a = unsafe { core::slice::from_raw_parts(&self as *const _ as *const u8, core::mem::size_of::()) }; - - buf[..a.len()].copy_from_slice(a); - } +impl MacCommand for ScanRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeScanReq; + const SIZE: usize = 20; } -pub union MacAddress { - pub short: [u8; 2], - pub extended: [u8; 8], +/// MLME SET Request used to attempt to write the given value to the indicated PIB attribute +#[repr(C)] +pub struct SetRequest { + /// the pointer to the value of the PIB attribute to set + pub pib_attribute_ptr: *const u8, + /// the name of the PIB attribute to set + pub pib_attribute: PibId, +} + +impl MacCommand for SetRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSetReq; + const SIZE: usize = 8; +} + +/// MLME START Request used by the FFDs to intiate a new PAN or to begin using a new superframe +/// configuration +#[derive(Default)] +pub struct StartRequest { + /// PAN indentifier to used by the device + pub pan_id: [u8; 2], + /// logical channel on which to begin + pub channel_number: u8, + /// channel page on which to begin + pub channel_page: u8, + /// time at which to begin transmitting beacons + pub start_time: [u8; 4], + /// indicated how often the beacon is to be transmitted + pub beacon_order: u8, + /// length of the active portion of the superframe + pub superframe_order: u8, + /// indicated wheter the device is a PAN coordinator or not + pub pan_coordinator: bool, + /// indicates if the receiver of the beaconing device is disabled or not + pub battery_life_extension: bool, + /// indicated if the coordinator realignment command is to be trasmitted + pub coord_realignment: u8, + /// indicated if the coordinator realignment command is to be trasmitted + pub coord_realign_security_level: u8, + /// index of the key to be used + pub coord_realign_key_id_index: u8, + /// originator of the key to be used + pub coord_realign_key_source: [u8; 8], + /// security level to be used for beacon frames + pub beacon_security_level: u8, + /// mode used to identify the key to be used + pub beacon_key_id_mode: u8, + /// index of the key to be used + pub beacon_key_index: u8, + /// originator of the key to be used + pub beacon_key_source: [u8; 8], +} + +impl MacCommand for StartRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeStartReq; + const SIZE: usize = 35; +} + +/// MLME SYNC Request used to synchronize with the coordinator by acquiring and, if +/// specified, tracking its beacons +pub struct SyncRequest { + /// the channel number on which to attempt coordinator synchronization + pub channel_number: u8, + /// the channel page on which to attempt coordinator synchronization + pub channel_page: u8, + /// `true` if the MLME is to synchronize with the next beacon and attempts + /// to track all future beacons. + /// + /// `false` if the MLME is to synchronize with only the next beacon + pub track_beacon: bool, +} + +impl MacCommand for SyncRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSyncReq; + const SIZE: usize = 4; +} + +/// MLME POLL Request propmts the device to request data from the coordinator +pub struct PollRequest { + /// addressing mode of the coordinator + pub coord_addr_mode: AddressMode, + /// security level to be used + pub security_level: u8, + /// mode used to identify the key to be used + pub key_id_mode: u8, + /// index of the key to be used + pub key_index: u8, + /// coordinator address + pub coord_address: MacAddress, + /// originator of the key to be used + pub key_source: [u8; 8], + /// PAN identifier of the coordinator + pub coord_pan_id: [u8; 2], +} + +impl MacCommand for PollRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmePollReq; + const SIZE: usize = 24; +} + +/// MLME DPS Request allows the next higher layer to request that the PHY utilize a +/// given pair of preamble codes for a single use pending expiration of the DPSIndexDuration +pub struct DpsRequest { + /// the index value for the transmitter + tx_dps_index: u8, + /// the index value of the receiver + rx_dps_index: u8, + /// the number of symbols for which the transmitter and receiver will utilize the + /// respective DPS indices + dps_index_duration: u8, +} + +impl MacCommand for DpsRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeDpsReq; + const SIZE: usize = 4; +} + +/// MLME SOUNDING request primitive which is used by the next higher layer to request that +/// the PHY respond with channel sounding information +pub struct SoundingRequest; + +impl MacCommand for SoundingRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeSoundingReq; + const SIZE: usize = 4; +} + +/// MLME CALIBRATE request primitive which used to obtain the results of a ranging +/// calibration request from an RDEV +pub struct CalibrateRequest; + +impl MacCommand for CalibrateRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeCalibrateReq; + const SIZE: usize = 4; +} + +/// MCPS DATA Request used for MAC data related requests from the application +pub struct DataRequest { + /// the handle assocated with the MSDU to be transmitted + pub msdu_ptr: *const u8, + /// source addressing mode used + pub src_addr_mode: AddressMode, + /// destination addressing mode used + pub dst_addr_mode: AddressMode, + /// destination PAN Id + pub dst_pan_id: [u8; 2], + /// destination address + pub dst_address: MacAddress, + /// the number of octets contained in the MSDU + pub msdu_length: u8, + /// the handle assocated with the MSDU to be transmitted + pub msdu_handle: u8, + /// the ACK transmittion options for the MSDU + pub ack_tx: u8, + /// `true` if a GTS is to be used for transmission + /// + /// `false` indicates that the CAP will be used + pub gts_tx: bool, + /// the pending bit transmission options for the MSDU + pub indirect_tx: u8, + /// the security level to be used + pub security_level: u8, + /// the mode used to indentify the key to be used + pub key_id_mode: u8, + /// the index of the key to be used + pub key_index: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], + /// 2011 - the pulse repitition value + pub uwbprf: u8, + /// 2011 - the ranging configuration + pub ranging: u8, + /// 2011 - the preamble symbol repititions + pub uwb_preamble_symbol_repetitions: u8, + /// 2011 - indicates the data rate + pub datrate: u8, +} + +impl MacCommand for DataRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsDataReq; + const SIZE: usize = 40; +} + +/// for MCPS PURGE Request used to purge an MSDU from the transaction queue +pub struct PurgeRequest { + /// the handle associated with the MSDU to be purged from the transaction + /// queue + pub msdu_handle: u8, +} + +impl MacCommand for PurgeRequest { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsPurgeReq; + const SIZE: usize = 4; +} + +/// MLME ASSOCIATE Response used to initiate a response to an MLME-ASSOCIATE.indication +pub struct AssociateResponse { + /// extended address of the device requesting association + pub device_address: [u8; 8], + /// 16-bitshort device address allocated by the coordinator on successful + /// association + pub assoc_short_address: [u8; 2], + /// status of the association attempt + pub status: u8, + /// security level to be used + pub security_level: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], + /// the mode used to identify the key to be used + pub key_id_mode: u8, + /// the index of the key to be used + pub key_index: u8, +} + +impl MacCommand for AssociateResponse { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeAssociateRes; + const SIZE: usize = 24; +} + +/// MLME ORPHAN Response used to respond to the MLME ORPHAN Indication +pub struct OrphanResponse { + /// extended address of the orphaned device + pub orphan_address: [u8; 8], + /// short address allocated to the orphaned device + pub short_address: [u8; 2], + /// if the orphaned device is associated with coordinator or not + pub associated_member: bool, + /// security level to be used + pub security_level: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], + /// the mode used to identify the key to be used + pub key_id_mode: u8, + /// the index of the key to be used + pub key_index: u8, +} + +impl MacCommand for OrphanResponse { + const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::MlmeOrphanRes; + const SIZE: usize = 24; } diff --git a/embassy-stm32-wpan/src/sub/mac/mod.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs index 83970a881..8e117d978 100644 --- a/embassy-stm32-wpan/src/sub/mac/mod.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -9,14 +9,17 @@ use embassy_stm32::ipcc::Ipcc; use embassy_sync::waitqueue::AtomicWaker; use self::commands::MacCommand; +use self::typedefs::MacStatus; use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::{EvtBox, EvtPacket}; use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; use crate::{channels, evt}; -pub mod commands; mod opcodes; +pub mod commands; +pub mod responses; +pub mod typedefs; static MAC_WAKER: AtomicWaker = AtomicWaker::new(); static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false); @@ -59,12 +62,25 @@ impl Mac { /// `HW_IPCC_MAC_802_15_4_CmdEvtNot` pub async fn write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { self.write(opcode, payload).await; - Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await; + Ipcc::flush(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL).await; unsafe { let p_event_packet = MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket; let p_mac_rsp_evt = &((*p_event_packet).evt_serial.evt.payload) as *const u8; + let evt_serial = (MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket) + .read_volatile() + .evt_serial; + let kind = (evt_serial).kind; + let evt_code = evt_serial.evt.evt_code; + let payload_len = evt_serial.evt.payload_len; + let payload = evt_serial.evt.payload; + + debug!( + "evt kind {} evt_code {} len {} payload {}", + kind, evt_code, payload_len, payload + ); + ptr::read_volatile(p_mac_rsp_evt) } } @@ -74,15 +90,32 @@ impl Mac { Ipcc::send(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL, || unsafe { CmdPacket::write_into( MAC_802_15_4_CMD_BUFFER.as_mut_ptr(), - TlPacketType::OtCmd, + TlPacketType::MacCmd, opcode, payload, ); }) .await; + + unsafe { + let typ = MAC_802_15_4_CMD_BUFFER.as_ptr().read_volatile().cmdserial.ty; + let cmd_code = MAC_802_15_4_CMD_BUFFER.as_ptr().read_volatile().cmdserial.cmd.cmd_code; + let payload_len = MAC_802_15_4_CMD_BUFFER + .as_ptr() + .read_volatile() + .cmdserial + .cmd + .payload_len; + let payload = MAC_802_15_4_CMD_BUFFER.as_ptr().read_volatile().cmdserial.cmd.payload; + + debug!( + "serial type {} cmd_code {} len {} payload {}", + typ, cmd_code, payload_len, payload + ); + } } - pub async fn send_command(&self, cmd: T) -> u8 + pub async fn send_command(&self, cmd: T) -> Result where T: MacCommand, { @@ -91,7 +124,9 @@ impl Mac { debug!("sending {:#x}", payload[..T::SIZE]); - self.write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]).await + let response = self.write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]).await; + + MacStatus::try_from(response) } } diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs new file mode 100644 index 000000000..e69de29bb diff --git a/embassy-stm32-wpan/src/sub/mac/typedefs.rs b/embassy-stm32-wpan/src/sub/mac/typedefs.rs new file mode 100644 index 000000000..d43d6e0cf --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/typedefs.rs @@ -0,0 +1,97 @@ +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum MacStatus { + Success = 0x00, + Error = 0x01, + NotImplemented = 0x02, + NotSupported = 0x03, + HardwareNotSupported = 0x04, + Undefined = 0x05, +} + +impl TryFrom for MacStatus { + type Error = (); + + fn try_from(value: u8) -> Result>::Error> { + match value { + 0x00 => Ok(Self::Success), + 0x01 => Ok(Self::Error), + 0x02 => Ok(Self::NotImplemented), + 0x03 => Ok(Self::NotSupported), + 0x04 => Ok(Self::HardwareNotSupported), + 0x05 => Ok(Self::Undefined), + _ => Err(()), + } + } +} + +/// this enum contains all the MAC PIB Ids +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum PibId { + // PHY + CurrentChannel = 0x00, + ChannelsSupported = 0x01, + TransmitPower = 0x02, + CCAMode = 0x03, + CurrentPage = 0x04, + MaxFrameDuration = 0x05, + SHRDuration = 0x06, + SymbolsPerOctet = 0x07, + + // MAC + AckWaitDuration = 0x40, + AssociationPermit = 0x41, + AutoRequest = 0x42, + BeaconPayload = 0x45, + BeaconPayloadLength = 0x46, + BeaconOrder = 0x47, + Bsn = 0x49, + CoordExtendedAdddress = 0x4A, + CoordShortAddress = 0x4B, + Dsn = 0x4C, + MaxFrameTotalWaitTime = 0x58, + MaxFrameRetries = 0x59, + PanId = 0x50, + ResponseWaitTime = 0x5A, + RxOnWhenIdle = 0x52, + SecurityEnabled = 0x5D, + ShortAddress = 0x53, + SuperframeOrder = 0x54, + TimestampSupported = 0x5C, + TransactionPersistenceTime = 0x55, + MaxBe = 0x57, + LifsPeriod = 0x5E, + SifsPeriod = 0x5F, + MaxCsmaBackoffs = 0x4E, + MinBe = 0x4F, + PanCoordinator = 0x10, + AssocPanCoordinator = 0x11, + ExtendedAddress = 0x6F, + AclEntryDescriptor = 0x70, + AclEntryDescriptorSize = 0x71, + DefaultSecurity = 0x72, + DefaultSecurityMaterialLength = 0x73, + DefaultSecurityMaterial = 0x74, + DefaultSecuritySuite = 0x75, + SecurityMode = 0x76, + CurrentAclEntries = 0x80, + DefaultSecurityExtendedAddress = 0x81, + AssociatedPanCoordinator = 0x56, + PromiscuousMode = 0x51, +} + +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum AddressMode { + NoAddress = 0x00, + Reserved = 0x01, + Short = 0x02, + Extended = 0x03, +} + +pub union MacAddress { + pub short: [u8; 2], + pub extended: [u8; 8], +} + +pub struct GtsCharacteristics { + pub fields: u8, +} diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 109734546..f23c8afa6 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -36,7 +36,7 @@ name = "tl_mbox_mac" required-features = ["mac"] [[bin]] -name = "tl_mbox_mac_2" +name = "mac_ffd" required-features = ["mac"] [[bin]] diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs new file mode 100644 index 000000000..4100d1ac5 --- /dev/null +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -0,0 +1,174 @@ +#![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::sub::mac::commands::{ResetRequest, SetRequest, StartRequest}; +use embassy_stm32_wpan::sub::mac::typedefs::PibId; +use embassy_stm32_wpan::sub::mm; +use embassy_stm32_wpan::TlMbox; +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::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"); + let response = mbox + .mac_subsystem + .send_command(ResetRequest { set_default_pib: true }) + .await; + info!("{}", response); + + info!("setting extended address"); + let extended_address: u64 = 0xACDE480000000001; + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &extended_address as *const _ as *const u8, + pib_attribute: PibId::ExtendedAddress, + }) + .await; + info!("{}", response); + + info!("setting short address"); + let short_address: u16 = 0x1122; + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &short_address as *const _ as *const u8, + pib_attribute: PibId::ShortAddress, + }) + .await; + info!("{}", response); + + info!("setting association permit"); + let association_permit: bool = true; + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &association_permit as *const _ as *const u8, + pib_attribute: PibId::AssociationPermit, + }) + .await; + info!("{}", response); + + info!("setting TX power"); + let transmit_power: i8 = 2; + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &transmit_power as *const _ as *const u8, + pib_attribute: PibId::TransmitPower, + }) + .await; + info!("{}", response); + + info!("starting FFD device"); + let response = mbox + .mac_subsystem + .send_command(StartRequest { + channel_number: 16, + beacon_order: 0x0F, + superframe_order: 0x0F, + pan_coordinator: true, + battery_life_extension: false, + ..Default::default() + }) + .await; + info!("{}", response); + + info!("setting RX on when idle"); + let rx_on_while_idle: bool = true; + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, + pib_attribute: PibId::RxOnWhenIdle, + }) + .await; + info!("{}", response); + + // info!("association request"); + // mbox.mac_subsystem + // .send_command(AssociateRequest { + // channel_number: 16, + // channel_page: 0, + // coord_addr_mode: 2, + // coord_address: MacAddress { short: [0x22, 0x11] }, + // capability_information: 0x80, + // coord_pan_id: [0xAA, 0x1A], + // security_level: 0, + + // key_id_mode: 0, + // key_index: 0, + // key_source: [0; 8], + // }) + // .await; + // info!("reading"); + // let result = mbox.mac_subsystem.read().await; + // info!("{}", result.payload()); + + // + // info!("starting ble..."); + // mbox.ble_subsystem.t_write(0x0c, &[]).await; + // + // info!("waiting for ble..."); + // let ble_event = mbox.ble_subsystem.tl_read().await; + // + // info!("ble event: {}", ble_event.payload()); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} diff --git a/examples/stm32wb/src/bin/tl_mbox_mac_2.rs b/examples/stm32wb/src/bin/mac_rfd.rs similarity index 72% rename from examples/stm32wb/src/bin/tl_mbox_mac_2.rs rename to examples/stm32wb/src/bin/mac_rfd.rs index e069adf87..938fe754f 100644 --- a/examples/stm32wb/src/bin/tl_mbox_mac_2.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -6,7 +6,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, MacAddress, ResetRequest, SetRequest}; +use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, ResetRequest, SetRequest, StartRequest}; +use embassy_stm32_wpan::sub::mac::typedefs::{AddressMode, MacAddress, PibId}; use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -71,46 +72,44 @@ async fn main(spawner: Spawner) { info!("{}", response); info!("setting extended address"); - let extended_address: u64 = 0xACDE480000000001; - defmt::debug!("{}", &extended_address as *const _ as *const u8); + let extended_address: u64 = 0xACDE480000000002; let response = mbox .mac_subsystem .send_command(SetRequest { pib_attribute_ptr: &extended_address as *const _ as *const u8, - pib_attribute: 0x6F, - stuffing: [0; 3], + pib_attribute: PibId::ExtendedAddress, }) .await; info!("{}", response); - // info!("association request"); - // mbox.mac_subsystem - // .send_command(AssociateRequest { - // channel_number: 16, - // channel_page: 0, - // coord_addr_mode: 2, - // coord_address: MacAddress { short: [0x22, 0x11] }, - // capability_information: 0x80, - // coord_pan_id: [0xAA, 0x1A], - // security_level: 0, + info!("assocation request"); + let response = mbox + .mac_subsystem + .send_command(AssociateRequest { + channel_number: 16, + channel_page: 0, + coord_addr_mode: AddressMode::Short, + coord_address: MacAddress { short: [0x22, 0x11] }, + capability_information: 0x80, + coord_pan_id: [0xAA, 0x1A], + security_level: 0x00, + key_id_mode: 0, + key_source: [0; 8], + key_index: 0, + }) + .await; + info!("{}", response); - // key_id_mode: 0, - // key_index: 0, - // key_source: [0; 8], - // }) - // .await; - // info!("reading"); - // let result = mbox.mac_subsystem.read().await; - // info!("{}", result.payload()); - - // - // info!("starting ble..."); - // mbox.ble_subsystem.t_write(0x0c, &[]).await; - // - // info!("waiting for ble..."); - // let ble_event = mbox.ble_subsystem.tl_read().await; - // - // info!("ble event: {}", ble_event.payload()); + info!("setting short address"); + let short: u64 = 0xACDE480000000002; + let response = mbox + .mac_subsystem + .send_command(SetRequest { + pib_attribute_ptr: &short as *const _ as *const u8, + pib_attribute: PibId::ShortAddress, + }) + .await; + info!("{}", response); info!("Test OK"); cortex_m::asm::bkpt(); From 67b14e6e7a98abc538adda45d6434ad44d700283 Mon Sep 17 00:00:00 2001 From: goueslati Date: Tue, 11 Jul 2023 16:54:48 +0100 Subject: [PATCH 03/13] wip: added MAC responses --- embassy-stm32-wpan/src/sub/mac/commands.rs | 17 ++ embassy-stm32-wpan/src/sub/mac/consts.rs | 3 + embassy-stm32-wpan/src/sub/mac/mod.rs | 3 +- embassy-stm32-wpan/src/sub/mac/responses.rs | 168 ++++++++++++++++++++ embassy-stm32-wpan/src/sub/mac/typedefs.rs | 27 ++++ 5 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 embassy-stm32-wpan/src/sub/mac/consts.rs diff --git a/embassy-stm32-wpan/src/sub/mac/commands.rs b/embassy-stm32-wpan/src/sub/mac/commands.rs index 3c234a3ce..4965a46eb 100644 --- a/embassy-stm32-wpan/src/sub/mac/commands.rs +++ b/embassy-stm32-wpan/src/sub/mac/commands.rs @@ -11,6 +11,7 @@ pub trait MacCommand { } /// MLME ASSOCIATE Request used to request an association +#[repr(C)] pub struct AssociateRequest { /// the logical channel on which to attempt association pub channel_number: u8, @@ -40,6 +41,7 @@ impl MacCommand for AssociateRequest { } /// MLME DISASSOCIATE Request sed to request a disassociation +#[repr(C)] pub struct DisassociateRequest { /// device addressing mode used pub device_addr_mode: AddressMode, @@ -67,6 +69,7 @@ impl MacCommand for DisassociateRequest { } /// MLME GET Request used to request a PIB value +#[repr(C)] pub struct GetRequest { /// the name of the PIB attribute to read pub pib_attribute: PibId, @@ -78,6 +81,7 @@ impl MacCommand for GetRequest { } /// MLME GTS Request used to request and maintain GTSs +#[repr(C)] pub struct GtsRequest { /// the characteristics of the GTS pub characteristics: GtsCharacteristics, @@ -96,6 +100,7 @@ impl MacCommand for GtsRequest { const SIZE: usize = 12; } +#[repr(C)] pub struct ResetRequest { /// MAC PIB attributes are set to their default values or not during reset pub set_default_pib: bool, @@ -108,6 +113,7 @@ impl MacCommand for ResetRequest { /// MLME RX ENABLE Request used to request that the receiver is either enabled /// for a finite period of time or disabled +#[repr(C)] pub struct RxEnableRequest { /// the request operation can be deferred or not pub defer_permit: bool, @@ -138,6 +144,7 @@ impl MacCommand for RxEnableRequest { } /// MLME SCAN Request used to initiate a channel scan over a given list of channels +#[repr(C)] pub struct ScanRequest { /// the type of scan to be performed pub scan_type: u8, @@ -179,6 +186,7 @@ impl MacCommand for SetRequest { /// MLME START Request used by the FFDs to intiate a new PAN or to begin using a new superframe /// configuration #[derive(Default)] +#[repr(C)] pub struct StartRequest { /// PAN indentifier to used by the device pub pan_id: [u8; 2], @@ -221,6 +229,7 @@ impl MacCommand for StartRequest { /// MLME SYNC Request used to synchronize with the coordinator by acquiring and, if /// specified, tracking its beacons +#[repr(C)] pub struct SyncRequest { /// the channel number on which to attempt coordinator synchronization pub channel_number: u8, @@ -239,6 +248,7 @@ impl MacCommand for SyncRequest { } /// MLME POLL Request propmts the device to request data from the coordinator +#[repr(C)] pub struct PollRequest { /// addressing mode of the coordinator pub coord_addr_mode: AddressMode, @@ -263,6 +273,7 @@ impl MacCommand for PollRequest { /// MLME DPS Request allows the next higher layer to request that the PHY utilize a /// given pair of preamble codes for a single use pending expiration of the DPSIndexDuration +#[repr(C)] pub struct DpsRequest { /// the index value for the transmitter tx_dps_index: u8, @@ -280,6 +291,7 @@ impl MacCommand for DpsRequest { /// MLME SOUNDING request primitive which is used by the next higher layer to request that /// the PHY respond with channel sounding information +#[repr(C)] pub struct SoundingRequest; impl MacCommand for SoundingRequest { @@ -289,6 +301,7 @@ impl MacCommand for SoundingRequest { /// MLME CALIBRATE request primitive which used to obtain the results of a ranging /// calibration request from an RDEV +#[repr(C)] pub struct CalibrateRequest; impl MacCommand for CalibrateRequest { @@ -297,6 +310,7 @@ impl MacCommand for CalibrateRequest { } /// MCPS DATA Request used for MAC data related requests from the application +#[repr(C)] pub struct DataRequest { /// the handle assocated with the MSDU to be transmitted pub msdu_ptr: *const u8, @@ -344,6 +358,7 @@ impl MacCommand for DataRequest { } /// for MCPS PURGE Request used to purge an MSDU from the transaction queue +#[repr(C)] pub struct PurgeRequest { /// the handle associated with the MSDU to be purged from the transaction /// queue @@ -356,6 +371,7 @@ impl MacCommand for PurgeRequest { } /// MLME ASSOCIATE Response used to initiate a response to an MLME-ASSOCIATE.indication +#[repr(C)] pub struct AssociateResponse { /// extended address of the device requesting association pub device_address: [u8; 8], @@ -380,6 +396,7 @@ impl MacCommand for AssociateResponse { } /// MLME ORPHAN Response used to respond to the MLME ORPHAN Indication +#[repr(C)] pub struct OrphanResponse { /// extended address of the orphaned device pub orphan_address: [u8; 8], diff --git a/embassy-stm32-wpan/src/sub/mac/consts.rs b/embassy-stm32-wpan/src/sub/mac/consts.rs new file mode 100644 index 000000000..dfbbadc67 --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/consts.rs @@ -0,0 +1,3 @@ +pub const MAX_ED_SCAN_RESULTS_SUPPORTED: usize = 16; +pub const MAX_PAN_DESC_SUPPORTED: usize = 6; +pub const MAX_SOUNDING_LIST_SUPPORTED: usize = 6; diff --git a/embassy-stm32-wpan/src/sub/mac/mod.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs index 8e117d978..6a3a057f4 100644 --- a/embassy-stm32-wpan/src/sub/mac/mod.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -16,8 +16,9 @@ use crate::evt::{EvtBox, EvtPacket}; use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; use crate::{channels, evt}; -mod opcodes; pub mod commands; +mod consts; +mod opcodes; pub mod responses; pub mod typedefs; diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index e69de29bb..7b240f370 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -0,0 +1,168 @@ +use super::consts::{MAX_ED_SCAN_RESULTS_SUPPORTED, MAX_PAN_DESC_SUPPORTED, MAX_SOUNDING_LIST_SUPPORTED}; +use super::typedefs::{AddressMode, MacAddress, PanDescriptor}; + +pub trait MacResponse { + const SIZE: usize; + + fn parse(buf: &[u8]) -> Self; +} + +/// MLME ASSOCIATE Confirm used to inform of the initiating device whether +/// its request to associate was successful or unsuccessful +pub struct AssociateConfirm { + /// short address allocated by the coordinator on successful association + pub assoc_short_address: [u8; 2], + /// status of the association request + pub status: u8, + /// security level to be used + pub security_level: u8, + /// the originator of the key to be used + pub key_source: [u8; 8], + /// the mode used to identify the key to be used + pub key_id_mode: u8, + /// the index of the key to be used + pub key_index: u8, +} + +/// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application. +pub struct DisassociateConfirm { + /// status of the disassociation attempt + pub status: u8, + /// device addressing mode used + pub device_addr_mode: AddressMode, + /// the identifier of the PAN of the device + pub device_pan_id: [u8; 2], + /// device address + pub device_address: MacAddress, +} + +/// MLME GET Confirm which requests information about a given PIB attribute +pub struct GetConfirm { + /// The pointer to the value of the PIB attribute attempted to read + pub pib_attribute_value_ptr: *const u8, + /// Status of the GET attempt + pub status: u8, + /// The name of the PIB attribute attempted to read + pub pib_attribute: u8, + /// The lenght of the PIB attribute Value return + pub pib_attribute_value_len: u8, +} + +/// MLME GTS Confirm which eports the results of a request to allocate a new GTS +/// or to deallocate an existing GTS +pub struct GtsConfirm { + /// The characteristics of the GTS + pub gts_characteristics: u8, + /// The status of the GTS reques + pub status: u8, +} + +/// MLME RESET Confirm which is used to report the results of the reset operation +pub struct ResetConfirm { + /// The result of the reset operation + status: u8, +} + +/// MLME RX ENABLE Confirm which is used to report the results of the attempt +/// to enable or disable the receiver +pub struct RxEnableConfirm { + /// Result of the request to enable or disable the receiver + status: u8, +} + +/// MLME SCAN Confirm which is used to report the result of the channel scan request +pub struct ScanConfirm { + /// Status of the scan request + pub status: u8, + /// The type of scan performed + pub scan_type: u8, + /// Channel page on which the scan was performed + pub channel_page: u8, + /// Channels given in the request which were not scanned + pub unscanned_channels: [u8; 4], + /// Number of elements returned in the appropriate result lists + pub result_list_size: u8, + /// List of energy measurements + pub energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED], + /// List of PAN descriptors + pub pan_descriptor_list: [PanDescriptor; MAX_PAN_DESC_SUPPORTED], + /// Categorization of energy detected in channel + pub detected_category: u8, + /// For UWB PHYs, the list of energy measurements taken + pub uwb_energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED], +} + +/// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute +pub struct SetConfirm { + /// The result of the set operation + pub status: u8, + /// The name of the PIB attribute that was written + pub pin_attribute: u8, +} + +/// MLME START Confirm which is used to report the results of the attempt to +/// start using a new superframe configuration +pub struct StartConfirm { + /// Result of the attempt to start using an updated superframe configuration + pub status: u8, +} + +/// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data +pub struct PollConfirm { + /// The status of the data request + pub status: u8, +} + +/// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide +/// channel sounding information +pub struct SoundingConfirm { + /// Results of the sounding measurement + sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED], +} + +/// MLME CALIBRATE Confirm which reports the result of a request to the PHY +/// to provide internal propagation path information +pub struct CalibrateConfirm { + /// The status of the attempt to return sounding data + pub status: u8, + /// A count of the propagation time from the ranging counter + /// to the transmit antenna + pub cal_tx_rmaker_offset: u32, + /// A count of the propagation time from the receive antenna + /// to the ranging counter + pub cal_rx_rmaker_offset: u32, +} + +/// MCPS DATA Confirm which will be used for reporting the results of +/// MAC data related requests from the application +pub struct DataConfirm { + /// The handle associated with the MSDU being confirmed + pub msdu_handle: u8, + /// The time, in symbols, at which the data were transmitted + pub a_time_stamp: [u8; 4], + /// ranging status + pub ranging_received: u8, + /// The status of the last MSDU transmission + pub status: u8, + /// time units corresponding to an RMARKER at the antenna at + /// the beginning of a ranging exchange + pub ranging_counter_start: u32, + /// time units corresponding to an RMARKER at the antenna + /// at the end of a ranging exchange + pub ranging_counter_stop: u32, + /// time units in a message exchange over which the tracking offset was measured + pub ranging_tracking_interval: u32, + /// time units slipped or advanced by the radio tracking system + pub ranging_offset: u32, + /// The FoM characterizing the ranging measurement + pub ranging_fom: u8, +} + +/// 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 +pub struct PurgeConfirm { + /// Handle associated with the MSDU requested to be purged from the transaction queue + pub msdu_handle: u8, + /// The status of the request + pub status: u8, +} diff --git a/embassy-stm32-wpan/src/sub/mac/typedefs.rs b/embassy-stm32-wpan/src/sub/mac/typedefs.rs index d43d6e0cf..7f0dd75c0 100644 --- a/embassy-stm32-wpan/src/sub/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/sub/mac/typedefs.rs @@ -95,3 +95,30 @@ pub union MacAddress { pub struct GtsCharacteristics { pub fields: u8, } + +/// MAC PAN Descriptor which contains the network details of the device from +/// which the beacon is received +pub struct PanDescriptor { + /// PAN identifier of the coordinator + pub a_coord_pan_id: [u8; 2], + /// Coordinator addressing mode + pub coord_addr_mode: AddressMode, + /// The current logical channel occupied by the network + pub logical_channel: u8, + /// Coordinator address + pub coord_addr: MacAddress, + /// The current channel page occupied by the network + pub channel_page: u8, + /// PAN coordinator is accepting GTS requests or not + pub gts_permit: bool, + /// Superframe specification as specified in the received beacon frame + pub a_superframe_spec: [u8; 2], + /// The time at which the beacon frame was received, in symbols + pub a_time_stamp: [u8; 4], + /// The LQI at which the network beacon was received + pub link_quality: u8, + /// Security level purportedly used by the received beacon frame + pub security_level: u8, + /// Byte Stuffing to keep 32 bit alignment + pub a_stuffing: [u8; 2], +} From fbddfcbfb7f732db593eecd5383742d9ce7308e7 Mon Sep 17 00:00:00 2001 From: goueslati Date: Tue, 11 Jul 2023 17:19:32 +0100 Subject: [PATCH 04/13] wip: added MAC indications --- embassy-stm32-wpan/src/sub/mac/consts.rs | 1 + embassy-stm32-wpan/src/sub/mac/indications.rs | 205 ++++++++++++++++++ embassy-stm32-wpan/src/sub/mac/mod.rs | 1 + embassy-stm32-wpan/src/sub/mac/responses.rs | 14 ++ 4 files changed, 221 insertions(+) create mode 100644 embassy-stm32-wpan/src/sub/mac/indications.rs diff --git a/embassy-stm32-wpan/src/sub/mac/consts.rs b/embassy-stm32-wpan/src/sub/mac/consts.rs index dfbbadc67..892d533b4 100644 --- a/embassy-stm32-wpan/src/sub/mac/consts.rs +++ b/embassy-stm32-wpan/src/sub/mac/consts.rs @@ -1,3 +1,4 @@ pub const MAX_ED_SCAN_RESULTS_SUPPORTED: usize = 16; pub const MAX_PAN_DESC_SUPPORTED: usize = 6; pub const MAX_SOUNDING_LIST_SUPPORTED: usize = 6; +pub const MAX_PENDING_ADDRESS: usize = 7; diff --git a/embassy-stm32-wpan/src/sub/mac/indications.rs b/embassy-stm32-wpan/src/sub/mac/indications.rs new file mode 100644 index 000000000..ebca16f72 --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/indications.rs @@ -0,0 +1,205 @@ +use super::consts::MAX_PENDING_ADDRESS; +use super::typedefs::{AddressMode, MacAddress, PanDescriptor}; + +/// MLME ASSOCIATE Indication which will be used by the MAC +/// to indicate the reception of an association request command +#[repr(C)] +pub struct AssociateIndication { + /// Extended address of the device requesting association + pub device_address: [u8; 8], + /// Operational capabilities of the device requesting association + pub capability_information: u8, + /// Security level purportedly used by the received MAC command frame + pub security_level: u8, + /// The mode used to identify the key used by the originator of frame + pub key_id_mode: u8, + /// Index of the key used by the originator of the received frame + pub key_index: u8, + /// The originator of the key used by the originator of the received frame + pub key_source: [u8; 8], +} + +/// MLME DISASSOCIATE indication which will be used to send +/// disassociation indication to the application. +#[repr(C)] +pub struct DisassociateIndication { + /// Extended address of the device requesting association + pub device_address: [u8; 8], + /// The reason for the disassociation + pub disassociate_reason: u8, + /// The security level to be used + pub security_level: u8, + /// The mode used to identify the key to be used + pub key_id_mode: u8, + /// The index of the key to be used + pub key_index: u8, + /// The originator of the key to be used + pub key_source: [u8; 8], +} + +/// MLME BEACON NOTIIFY Indication which is used to send parameters contained +/// within a beacon frame received by the MAC to the application +#[repr(C)] +pub struct BeaconNotifyIndication { + /// he set of octets comprising the beacon payload to be transferred + /// from the MAC sublayer entity to the next higher layer + pub sdu_ptr: *const u8, + /// The PAN Descriptor for the received beacon + pub pan_descriptor: PanDescriptor, + /// The list of addresses of the devices + pub addr_list: [MacAddress; MAX_PENDING_ADDRESS], + /// Beacon Sequence Number + pub bsn: u8, + /// The beacon pending address specification + pub pend_addr_spec: u8, + /// Number of octets contained in the beacon payload of the beacon frame + pub sdu_length: u8, +} + +/// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status +#[repr(C)] +pub struct CommStatusIndication { + /// The 16-bit PAN identifier of the device from which the frame + /// was received or to which the frame was being sent + pub pan_id: [u8; 2], + /// Source addressing mode + pub src_addr_mode: AddressMode, + /// Destination addressing mode + pub dst_addr_mode: AddressMode, + /// Source address + pub src_address: MacAddress, + /// Destination address + pub dst_address: MacAddress, + /// The communications status + pub status: u8, + /// Security level to be used + pub security_level: u8, + /// Mode used to identify the key to be used + pub key_id_mode: u8, + /// Index of the key to be used + pub key_index: u8, + /// Originator of the key to be used + pub key_source: [u8; 8], +} + +/// MLME GTS Indication indicates that a GTS has been allocated or that a +/// previously allocated GTS has been deallocated +#[repr(C)] +pub struct GtsIndication { + /// The short address of the device that has been allocated or deallocated a GTS + pub device_address: [u8; 2], + /// The characteristics of the GTS + pub gts_characteristics: u8, + /// Security level to be used + pub security_level: u8, + /// Mode used to identify the key to be used + pub key_id_mode: u8, + /// Index of the key to be used + pub key_index: u8, + /// Originator of the key to be used + pub key_source: [u8; 8], +} + +/// MLME ORPHAN Indication which is used by the coordinator to notify the +/// application of the presence of an orphaned device +#[repr(C)] +pub struct OrphanIndication { + /// Extended address of the orphaned device + pub orphan_address: [u8; 8], + /// Originator of the key used by the originator of the received frame + pub key_source: [u8; 8], + /// Security level purportedly used by the received MAC command frame + pub security_level: u8, + /// Mode used to identify the key used by originator of received frame + pub key_id_mode: u8, + /// Index of the key used by the originator of the received frame + pub key_index: u8, +} + +/// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss +/// of synchronization with the coordinator +#[repr(C)] +pub struct SyncLossIndication { + /// The PAN identifier with which the device lost synchronization or to which it was realigned + pub pan_id: [u8; 2], + /// The reason that synchronization was lost + pub loss_reason: u8, + /// The logical channel on which the device lost synchronization or to whi + pub channel_number: u8, + /// The channel page on which the device lost synchronization or to which + pub channel_page: u8, + /// The security level used by the received MAC frame + pub security_level: u8, + /// Mode used to identify the key used by originator of received frame + pub key_id_mode: u8, + /// Index of the key used by the originator of the received frame + pub key_index: u8, + /// Originator of the key used by the originator of the received frame + pub key_source: [u8; 8], +} + +/// MLME DPS Indication which indicates the expiration of the DPSIndexDuration +/// and the resetting of the DPS values in the PHY +pub struct DpsIndication; + +#[repr(C)] +pub struct DataIndication { + /// Pointer to the set of octets forming the MSDU being indicated + pub msdu_ptr: *const u8, + /// Source addressing mode used + pub src_addr_mode: u8, + /// Source PAN ID + pub src_pan_id: [u8; 2], + /// Source address + pub src_address: MacAddress, + /// Destination addressing mode used + pub dst_addr_mode: AddressMode, + /// Destination PAN ID + pub dst_pan_id: [u8; 2], + /// Destination address + pub dst_address: MacAddress, + /// The number of octets contained in the MSDU being indicated + pub msdu_length: u8, + /// QI value measured during reception of the MPDU + pub mpdu_link_quality: u8, + /// The data sequence number of the received data frame + pub dsn: u8, + /// The time, in symbols, at which the data were received + pub time_stamp: [u8; 4], + /// The security level purportedly used by the received data frame + pub security_level: u8, + /// Mode used to identify the key used by originator of received frame + pub key_id_mode: u8, + /// The originator of the key + pub key_source: [u8; 8], + /// The index of the key + pub key_index: u8, + /// he pulse repetition value of the received PPDU + pub uwbprf: u8, + /// The preamble symbol repetitions of the UWB PHY frame + pub uwn_preamble_symbol_repetitions: u8, + /// Indicates the data rate + pub datrate: u8, + /// time units corresponding to an RMARKER at the antenna at the end of a ranging exchange, + pub ranging_received: u8, + pub ranging_counter_start: u32, + pub ranging_counter_stop: u32, + /// ime units in a message exchange over which the tracking offset was measured + pub ranging_tracking_interval: u32, + /// time units slipped or advanced by the radio tracking system + pub ranging_offset: u32, + /// The FoM characterizing the ranging measurement + pub ranging_fom: u8, + /// The Received Signal Strength Indicator measured + pub rssi: u8, +} + +/// 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)] +pub struct PollIndication { + /// addressing mode used + pub addr_mode: u8, + /// Poll requester address + pub request_address: MacAddress, +} diff --git a/embassy-stm32-wpan/src/sub/mac/mod.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs index 6a3a057f4..756d7d5b1 100644 --- a/embassy-stm32-wpan/src/sub/mac/mod.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -18,6 +18,7 @@ use crate::{channels, evt}; pub mod commands; mod consts; +pub mod indications; mod opcodes; pub mod responses; pub mod typedefs; diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index 7b240f370..8c30a1823 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -9,6 +9,7 @@ pub trait MacResponse { /// MLME ASSOCIATE Confirm used to inform of the initiating device whether /// its request to associate was successful or unsuccessful +#[repr(C)] pub struct AssociateConfirm { /// short address allocated by the coordinator on successful association pub assoc_short_address: [u8; 2], @@ -25,6 +26,7 @@ pub struct AssociateConfirm { } /// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application. +#[repr(C)] pub struct DisassociateConfirm { /// status of the disassociation attempt pub status: u8, @@ -37,6 +39,7 @@ pub struct DisassociateConfirm { } /// MLME GET Confirm which requests information about a given PIB attribute +#[repr(C)] pub struct GetConfirm { /// The pointer to the value of the PIB attribute attempted to read pub pib_attribute_value_ptr: *const u8, @@ -50,6 +53,7 @@ pub struct GetConfirm { /// MLME GTS Confirm which eports the results of a request to allocate a new GTS /// or to deallocate an existing GTS +#[repr(C)] pub struct GtsConfirm { /// The characteristics of the GTS pub gts_characteristics: u8, @@ -58,6 +62,7 @@ pub struct GtsConfirm { } /// MLME RESET Confirm which is used to report the results of the reset operation +#[repr(C)] pub struct ResetConfirm { /// The result of the reset operation status: u8, @@ -65,12 +70,14 @@ pub struct ResetConfirm { /// MLME RX ENABLE Confirm which is used to report the results of the attempt /// to enable or disable the receiver +#[repr(C)] pub struct RxEnableConfirm { /// Result of the request to enable or disable the receiver status: u8, } /// MLME SCAN Confirm which is used to report the result of the channel scan request +#[repr(C)] pub struct ScanConfirm { /// Status of the scan request pub status: u8, @@ -93,6 +100,7 @@ pub struct ScanConfirm { } /// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute +#[repr(C)] pub struct SetConfirm { /// The result of the set operation pub status: u8, @@ -102,12 +110,14 @@ pub struct SetConfirm { /// MLME START Confirm which is used to report the results of the attempt to /// start using a new superframe configuration +#[repr(C)] pub struct StartConfirm { /// Result of the attempt to start using an updated superframe configuration pub status: u8, } /// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data +#[repr(C)] pub struct PollConfirm { /// The status of the data request pub status: u8, @@ -115,6 +125,7 @@ pub struct PollConfirm { /// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide /// channel sounding information +#[repr(C)] pub struct SoundingConfirm { /// Results of the sounding measurement sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED], @@ -122,6 +133,7 @@ pub struct SoundingConfirm { /// MLME CALIBRATE Confirm which reports the result of a request to the PHY /// to provide internal propagation path information +#[repr(C)] pub struct CalibrateConfirm { /// The status of the attempt to return sounding data pub status: u8, @@ -135,6 +147,7 @@ pub struct CalibrateConfirm { /// MCPS DATA Confirm which will be used for reporting the results of /// MAC data related requests from the application +#[repr(C)] pub struct DataConfirm { /// The handle associated with the MSDU being confirmed pub msdu_handle: u8, @@ -160,6 +173,7 @@ pub struct 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)] pub struct PurgeConfirm { /// Handle associated with the MSDU requested to be purged from the transaction queue pub msdu_handle: u8, From d5a4457b5e3a95a12f249315fb1d9b6a577307f2 Mon Sep 17 00:00:00 2001 From: goueslati Date: Wed, 12 Jul 2023 15:06:56 +0100 Subject: [PATCH 05/13] parsing MAC structs --- embassy-stm32-wpan/Cargo.toml | 7 +- embassy-stm32-wpan/src/sub/mac/commands.rs | 55 +-- embassy-stm32-wpan/src/sub/mac/event.rs | 94 +++++ embassy-stm32-wpan/src/sub/mac/helpers.rs | 7 + embassy-stm32-wpan/src/sub/mac/indications.rs | 295 ++++++++++++-- embassy-stm32-wpan/src/sub/mac/macros.rs | 32 ++ embassy-stm32-wpan/src/sub/mac/mod.rs | 63 ++- embassy-stm32-wpan/src/sub/mac/opcodes.rs | 63 +++ embassy-stm32-wpan/src/sub/mac/responses.rs | 302 +++++++++++++-- embassy-stm32-wpan/src/sub/mac/typedefs.rs | 359 ++++++++++++++---- examples/stm32wb/src/bin/mac_ffd.rs | 99 ++--- examples/stm32wb/src/bin/mac_rfd.rs | 14 +- 12 files changed, 1107 insertions(+), 283 deletions(-) create mode 100644 embassy-stm32-wpan/src/sub/mac/event.rs create mode 100644 embassy-stm32-wpan/src/sub/mac/helpers.rs create mode 100644 embassy-stm32-wpan/src/sub/mac/macros.rs diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 4b5dcdd29..1325faed9 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -26,13 +26,14 @@ aligned = "0.4.1" bit_field = "0.10.2" stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } stm32wb-hci = { version = "0.1.2", features = ["version-5-0"], optional = true } +bitflags = { version = "2.3.3", optional = true } [features] -default = ["stm32wb55rg", "mac", "ble"] +default = ["stm32wb55rg", "mac", "ble", "defmt"] defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] ble = ["dep:stm32wb-hci"] -mac = [] +mac = ["dep:bitflags"] stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] @@ -49,4 +50,4 @@ stm32wb55rg = [ "embassy-stm32/stm32wb55rg" ] stm32wb55vc = [ "embassy-stm32/stm32wb55vc" ] stm32wb55ve = [ "embassy-stm32/stm32wb55ve" ] stm32wb55vg = [ "embassy-stm32/stm32wb55vg" ] -stm32wb55vy = [ "embassy-stm32/stm32wb55vy" ] \ No newline at end of file +stm32wb55vy = [ "embassy-stm32/stm32wb55vy" ] diff --git a/embassy-stm32-wpan/src/sub/mac/commands.rs b/embassy-stm32-wpan/src/sub/mac/commands.rs index 4965a46eb..d8a4e3ee1 100644 --- a/embassy-stm32-wpan/src/sub/mac/commands.rs +++ b/embassy-stm32-wpan/src/sub/mac/commands.rs @@ -1,5 +1,8 @@ use super::opcodes::OpcodeM4ToM0; -use super::typedefs::{AddressMode, GtsCharacteristics, MacAddress, PibId}; +use super::typedefs::{ + AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, PibId, + ScanType, SecurityLevel, +}; pub trait MacCommand { const OPCODE: OpcodeM4ToM0; @@ -14,19 +17,19 @@ pub trait MacCommand { #[repr(C)] pub struct AssociateRequest { /// the logical channel on which to attempt association - pub channel_number: u8, + pub channel_number: MacChannel, /// the channel page on which to attempt association pub channel_page: u8, /// coordinator addressing mode pub coord_addr_mode: AddressMode, /// operational capabilities of the associating device - pub capability_information: u8, + pub capability_information: Capabilities, /// the identifier of the PAN with which to associate pub coord_pan_id: [u8; 2], /// the security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the originator of the key to be used pub key_source: [u8; 8], /// Coordinator address @@ -48,15 +51,15 @@ pub struct DisassociateRequest { /// the identifier of the PAN of the device pub device_pan_id: [u8; 2], /// the reason for the disassociation - pub disassociate_reason: u8, + pub disassociation_reason: DisassociationReason, /// device address pub device_address: MacAddress, /// `true` if the disassociation notification command is to be sent indirectly pub tx_indirect: bool, /// the security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the mode to be used to indetify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, /// the originator of the key to be used @@ -86,9 +89,9 @@ pub struct GtsRequest { /// the characteristics of the GTS pub characteristics: GtsCharacteristics, /// the security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, /// the originator of the key to be used @@ -147,19 +150,19 @@ impl MacCommand for RxEnableRequest { #[repr(C)] pub struct ScanRequest { /// the type of scan to be performed - pub scan_type: u8, + pub scan_type: ScanType, /// the time spent on scanning each channel pub scan_duration: u8, /// channel page on which to perform the scan pub channel_page: u8, /// security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// indicate which channels are to be scanned pub scan_channels: [u8; 4], /// originator the key to be used pub key_source: [u8; 8], /// mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// index of the key to be used pub key_index: u8, } @@ -191,7 +194,7 @@ pub struct StartRequest { /// PAN indentifier to used by the device pub pan_id: [u8; 2], /// logical channel on which to begin - pub channel_number: u8, + pub channel_number: MacChannel, /// channel page on which to begin pub channel_page: u8, /// time at which to begin transmitting beacons @@ -207,15 +210,15 @@ pub struct StartRequest { /// indicated if the coordinator realignment command is to be trasmitted pub coord_realignment: u8, /// indicated if the coordinator realignment command is to be trasmitted - pub coord_realign_security_level: u8, + pub coord_realign_security_level: SecurityLevel, /// index of the key to be used pub coord_realign_key_id_index: u8, /// originator of the key to be used pub coord_realign_key_source: [u8; 8], /// security level to be used for beacon frames - pub beacon_security_level: u8, + pub beacon_security_level: SecurityLevel, /// mode used to identify the key to be used - pub beacon_key_id_mode: u8, + pub beacon_key_id_mode: KeyIdMode, /// index of the key to be used pub beacon_key_index: u8, /// originator of the key to be used @@ -232,7 +235,7 @@ impl MacCommand for StartRequest { #[repr(C)] pub struct SyncRequest { /// the channel number on which to attempt coordinator synchronization - pub channel_number: u8, + pub channel_number: MacChannel, /// the channel page on which to attempt coordinator synchronization pub channel_page: u8, /// `true` if the MLME is to synchronize with the next beacon and attempts @@ -253,9 +256,9 @@ pub struct PollRequest { /// addressing mode of the coordinator pub coord_addr_mode: AddressMode, /// security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// index of the key to be used pub key_index: u8, /// coordinator address @@ -335,9 +338,9 @@ pub struct DataRequest { /// the pending bit transmission options for the MSDU pub indirect_tx: u8, /// the security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the mode used to indentify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, /// the originator of the key to be used @@ -381,11 +384,11 @@ pub struct AssociateResponse { /// status of the association attempt pub status: u8, /// security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the originator of the key to be used pub key_source: [u8; 8], /// the mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, } @@ -405,11 +408,11 @@ pub struct OrphanResponse { /// if the orphaned device is associated with coordinator or not pub associated_member: bool, /// security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the originator of the key to be used pub key_source: [u8; 8], /// the mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, } diff --git a/embassy-stm32-wpan/src/sub/mac/event.rs b/embassy-stm32-wpan/src/sub/mac/event.rs new file mode 100644 index 000000000..aaf965565 --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/event.rs @@ -0,0 +1,94 @@ +use super::helpers::to_u16; +use super::indications::{ + AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication, + DpsIndication, GtsIndication, OrphanIndication, PollIndication, SyncLossIndication, +}; +use super::responses::{ + AssociateConfirm, CalibrateConfirm, DataConfirm, DisassociateConfirm, DpsConfirm, GetConfirm, GtsConfirm, + PollConfirm, PurgeConfirm, ResetConfirm, RxEnableConfirm, ScanConfirm, SetConfirm, SoundingConfirm, StartConfirm, +}; +use crate::sub::mac::opcodes::OpcodeM0ToM4; + +pub trait ParseableMacEvent { + const SIZE: usize; + + fn validate(buf: &[u8]) -> Result<(), ()> { + if buf.len() < Self::SIZE { + return Err(()); + } + + Ok(()) + } + + fn try_parse(buf: &[u8]) -> Result + where + Self: Sized; +} + +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum MacEvent { + MlmeAssociateCnf(AssociateConfirm), + MlmeDisassociateCnf(DisassociateConfirm), + MlmeGetCnf(GetConfirm), + MlmeGtsCnf(GtsConfirm), + MlmeResetCnf(ResetConfirm), + MlmeRxEnableCnf(RxEnableConfirm), + MlmeScanCnf(ScanConfirm), + MlmeSetCnf(SetConfirm), + MlmeStartCnf(StartConfirm), + MlmePollCnf(PollConfirm), + MlmeDpsCnf(DpsConfirm), + MlmeSoundingCnf(SoundingConfirm), + MlmeCalibrateCnf(CalibrateConfirm), + McpsDataCnf(DataConfirm), + McpsPurgeCnf(PurgeConfirm), + MlmeAssociateInd(AssociateIndication), + MlmeDisassociateInd(DisassociateIndication), + MlmeBeaconNotifyInd(BeaconNotifyIndication), + MlmeCommStatusInd(CommStatusIndication), + MlmeGtsInd(GtsIndication), + MlmeOrphanInd(OrphanIndication), + MlmeSyncLossInd(SyncLossIndication), + MlmeDpsInd(DpsIndication), + McpsDataInd(DataIndication), + MlmePollInd(PollIndication), +} + +impl TryFrom<&[u8]> for MacEvent { + type Error = (); + + fn try_from(value: &[u8]) -> Result { + let opcode = to_u16(&value[0..2]); + let opcode = OpcodeM0ToM4::try_from(opcode)?; + + let buf = &value[2..]; + + match opcode { + OpcodeM0ToM4::MlmeAssociateCnf => Ok(Self::MlmeAssociateCnf(AssociateConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeDisassociateCnf => Ok(Self::MlmeDisassociateCnf(DisassociateConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeGetCnf => Ok(Self::MlmeGetCnf(GetConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeGtsCnf => Ok(Self::MlmeGtsCnf(GtsConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeResetCnf => Ok(Self::MlmeResetCnf(ResetConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeRxEnableCnf => Ok(Self::MlmeRxEnableCnf(RxEnableConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeScanCnf => Ok(Self::MlmeScanCnf(ScanConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeSetCnf => Ok(Self::MlmeSetCnf(SetConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeStartCnf => Ok(Self::MlmeStartCnf(StartConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmePollCnf => Ok(Self::MlmePollCnf(PollConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeDpsCnf => Ok(Self::MlmeDpsCnf(DpsConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeSoundingCnf => Ok(Self::MlmeSoundingCnf(SoundingConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeCalibrateCnf => Ok(Self::MlmeCalibrateCnf(CalibrateConfirm::try_parse(buf)?)), + OpcodeM0ToM4::McpsDataCnf => Ok(Self::McpsDataCnf(DataConfirm::try_parse(buf)?)), + OpcodeM0ToM4::McpsPurgeCnf => Ok(Self::McpsPurgeCnf(PurgeConfirm::try_parse(buf)?)), + OpcodeM0ToM4::MlmeAssociateInd => Ok(Self::MlmeAssociateInd(AssociateIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeDisassociateInd => Ok(Self::MlmeDisassociateInd(DisassociateIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeBeaconNotifyInd => Ok(Self::MlmeBeaconNotifyInd(BeaconNotifyIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeCommStatusInd => Ok(Self::MlmeCommStatusInd(CommStatusIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeGtsInd => Ok(Self::MlmeGtsInd(GtsIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeOrphanInd => Ok(Self::MlmeOrphanInd(OrphanIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeSyncLossInd => Ok(Self::MlmeSyncLossInd(SyncLossIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmeDpsInd => Ok(Self::MlmeDpsInd(DpsIndication::try_parse(buf)?)), + OpcodeM0ToM4::McpsDataInd => Ok(Self::McpsDataInd(DataIndication::try_parse(buf)?)), + OpcodeM0ToM4::MlmePollInd => Ok(Self::MlmePollInd(PollIndication::try_parse(buf)?)), + } + } +} diff --git a/embassy-stm32-wpan/src/sub/mac/helpers.rs b/embassy-stm32-wpan/src/sub/mac/helpers.rs new file mode 100644 index 000000000..5a5bf8a85 --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/helpers.rs @@ -0,0 +1,7 @@ +pub fn to_u16(buf: &[u8]) -> u16 { + ((buf[1] as u16) << 8) | buf[0] as u16 +} + +pub fn to_u32(buf: &[u8]) -> u32 { + ((buf[0] as u32) << 0) + ((buf[1] as u32) << 8) + ((buf[2] as u32) << 16) + ((buf[3] as u32) << 24) +} diff --git a/embassy-stm32-wpan/src/sub/mac/indications.rs b/embassy-stm32-wpan/src/sub/mac/indications.rs index ebca16f72..dc5ae4c44 100644 --- a/embassy-stm32-wpan/src/sub/mac/indications.rs +++ b/embassy-stm32-wpan/src/sub/mac/indications.rs @@ -1,45 +1,84 @@ use super::consts::MAX_PENDING_ADDRESS; -use super::typedefs::{AddressMode, MacAddress, PanDescriptor}; +use super::event::ParseableMacEvent; +use super::helpers::to_u32; +use super::typedefs::{ + AddressMode, Capabilities, DisassociationReason, KeyIdMode, MacAddress, MacChannel, MacStatus, PanDescriptor, + SecurityLevel, +}; /// MLME ASSOCIATE Indication which will be used by the MAC /// to indicate the reception of an association request command -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateIndication { /// Extended address of the device requesting association pub device_address: [u8; 8], /// Operational capabilities of the device requesting association - pub capability_information: u8, + pub capability_information: Capabilities, /// Security level purportedly used by the received MAC command frame - pub security_level: u8, + pub security_level: SecurityLevel, /// The mode used to identify the key used by the originator of frame - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// Index of the key used by the originator of the received frame pub key_index: u8, /// The originator of the key used by the originator of the received frame pub key_source: [u8; 8], } +impl ParseableMacEvent for AssociateIndication { + const SIZE: usize = 20; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + device_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], + capability_information: Capabilities::from_bits(buf[8]).ok_or(())?, + security_level: SecurityLevel::try_from(buf[9])?, + key_id_mode: KeyIdMode::try_from(buf[10])?, + key_index: buf[11], + key_source: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]], + }) + } +} + /// MLME DISASSOCIATE indication which will be used to send /// disassociation indication to the application. -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DisassociateIndication { /// Extended address of the device requesting association pub device_address: [u8; 8], /// The reason for the disassociation - pub disassociate_reason: u8, + pub disassociation_reason: DisassociationReason, /// The security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// The mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// The index of the key to be used pub key_index: u8, /// The originator of the key to be used pub key_source: [u8; 8], } +impl ParseableMacEvent for DisassociateIndication { + const SIZE: usize = 20; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + device_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], + disassociation_reason: DisassociationReason::try_from(buf[8])?, + security_level: SecurityLevel::try_from(buf[9])?, + key_id_mode: KeyIdMode::try_from(buf[10])?, + key_index: buf[11], + key_source: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]], + }) + } +} + /// MLME BEACON NOTIIFY Indication which is used to send parameters contained /// within a beacon frame received by the MAC to the application -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct BeaconNotifyIndication { /// he set of octets comprising the beacon payload to be transferred /// from the MAC sublayer entity to the next higher layer @@ -56,8 +95,18 @@ pub struct BeaconNotifyIndication { pub sdu_length: u8, } +impl ParseableMacEvent for BeaconNotifyIndication { + const SIZE: usize = 12; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + todo!() + } +} + /// MLME COMM STATUS Indication which is used by the MAC to indicate a communications status -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CommStatusIndication { /// The 16-bit PAN identifier of the device from which the frame /// was received or to which the frame was being sent @@ -71,83 +120,190 @@ pub struct CommStatusIndication { /// Destination address pub dst_address: MacAddress, /// The communications status - pub status: u8, + pub status: MacStatus, /// Security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// Mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// Index of the key to be used pub key_index: u8, /// Originator of the key to be used pub key_source: [u8; 8], } +impl ParseableMacEvent for CommStatusIndication { + const SIZE: usize = 32; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + let src_addr_mode = AddressMode::try_from(buf[2])?; + let dst_addr_mode = AddressMode::try_from(buf[3])?; + + let src_address = match src_addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[4], buf[5]]), + AddressMode::Extended => { + MacAddress::Extended([buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]]) + } + }; + + let dst_address = match dst_addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[12], buf[13]]), + AddressMode::Extended => { + MacAddress::Extended([buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]]) + } + }; + + Ok(Self { + pan_id: [buf[0], buf[1]], + src_addr_mode, + dst_addr_mode, + src_address, + dst_address, + status: MacStatus::try_from(buf[20])?, + security_level: SecurityLevel::try_from(buf[21])?, + key_id_mode: KeyIdMode::try_from(buf[22])?, + key_index: buf[23], + key_source: [buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31]], + }) + } +} + /// MLME GTS Indication indicates that a GTS has been allocated or that a /// previously allocated GTS has been deallocated -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsIndication { /// The short address of the device that has been allocated or deallocated a GTS pub device_address: [u8; 2], /// The characteristics of the GTS pub gts_characteristics: u8, /// Security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// Mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// Index of the key to be used pub key_index: u8, /// Originator of the key to be used pub key_source: [u8; 8], } +impl ParseableMacEvent for GtsIndication { + const SIZE: usize = 16; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + device_address: [buf[0], buf[1]], + gts_characteristics: buf[2], + security_level: SecurityLevel::try_from(buf[3])?, + key_id_mode: KeyIdMode::try_from(buf[4])?, + key_index: buf[5], + // 2 byte stuffing + key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]], + }) + } +} + /// MLME ORPHAN Indication which is used by the coordinator to notify the /// application of the presence of an orphaned device -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct OrphanIndication { /// Extended address of the orphaned device pub orphan_address: [u8; 8], /// Originator of the key used by the originator of the received frame pub key_source: [u8; 8], /// Security level purportedly used by the received MAC command frame - pub security_level: u8, + pub security_level: SecurityLevel, /// Mode used to identify the key used by originator of received frame - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// Index of the key used by the originator of the received frame pub key_index: u8, } +impl ParseableMacEvent for OrphanIndication { + const SIZE: usize = 20; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + orphan_address: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], + key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]], + security_level: SecurityLevel::try_from(buf[16])?, + key_id_mode: KeyIdMode::try_from(buf[17])?, + key_index: buf[18], + // 1 byte stuffing + }) + } +} + /// MLME SYNC LOSS Indication which is used by the MAC to indicate the loss /// of synchronization with the coordinator -#[repr(C)] +#[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 pub pan_id: [u8; 2], /// The reason that synchronization was lost pub loss_reason: u8, /// The logical channel on which the device lost synchronization or to whi - pub channel_number: u8, + pub channel_number: MacChannel, /// The channel page on which the device lost synchronization or to which pub channel_page: u8, /// The security level used by the received MAC frame - pub security_level: u8, + pub security_level: SecurityLevel, /// Mode used to identify the key used by originator of received frame - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// Index of the key used by the originator of the received frame pub key_index: u8, /// Originator of the key used by the originator of the received frame pub key_source: [u8; 8], } +impl ParseableMacEvent for SyncLossIndication { + const SIZE: usize = 16; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + pan_id: [buf[0], buf[1]], + loss_reason: buf[2], + channel_number: MacChannel::try_from(buf[3])?, + channel_page: buf[4], + security_level: SecurityLevel::try_from(buf[5])?, + key_id_mode: KeyIdMode::try_from(buf[6])?, + key_index: buf[7], + key_source: [buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]], + }) + } +} + /// MLME DPS Indication which indicates the expiration of the DPSIndexDuration /// and the resetting of the DPS values in the PHY +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DpsIndication; -#[repr(C)] +impl ParseableMacEvent for DpsIndication { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self) + } +} + +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DataIndication { /// Pointer to the set of octets forming the MSDU being indicated pub msdu_ptr: *const u8, /// Source addressing mode used - pub src_addr_mode: u8, + pub src_addr_mode: AddressMode, /// Source PAN ID pub src_pan_id: [u8; 2], /// Source address @@ -167,9 +323,9 @@ pub struct DataIndication { /// The time, in symbols, at which the data were received pub time_stamp: [u8; 4], /// The security level purportedly used by the received data frame - pub security_level: u8, + pub security_level: SecurityLevel, /// Mode used to identify the key used by originator of received frame - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// The originator of the key pub key_source: [u8; 8], /// The index of the key @@ -194,12 +350,91 @@ pub struct DataIndication { pub rssi: u8, } +impl ParseableMacEvent for DataIndication { + const SIZE: usize = 72; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + let src_addr_mode = AddressMode::try_from(buf[4])?; + let src_address = match src_addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[7], buf[8]]), + AddressMode::Extended => { + MacAddress::Extended([buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14]]) + } + }; + + let dst_addr_mode = AddressMode::try_from(buf[15])?; + let dst_address = match dst_addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[18], buf[19]]), + AddressMode::Extended => { + MacAddress::Extended([buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], buf[24], buf[25]]) + } + }; + + Ok(Self { + msdu_ptr: to_u32(&buf[0..4]) as *const u8, + src_addr_mode, + src_pan_id: [buf[5], buf[6]], + src_address, + dst_addr_mode, + dst_pan_id: [buf[16], buf[17]], + dst_address, + msdu_length: buf[26], + mpdu_link_quality: buf[27], + dsn: buf[28], + time_stamp: [buf[29], buf[30], buf[31], buf[32]], + security_level: SecurityLevel::try_from(buf[33])?, + key_id_mode: KeyIdMode::try_from(buf[34])?, + key_source: [buf[35], buf[36], buf[37], buf[38], buf[39], buf[40], buf[41], buf[42]], + key_index: buf[43], + uwbprf: buf[44], + uwn_preamble_symbol_repetitions: buf[45], + datrate: buf[46], + ranging_received: buf[47], + ranging_counter_start: to_u32(&buf[58..52]), + ranging_counter_stop: to_u32(&buf[52..56]), + ranging_tracking_interval: to_u32(&buf[56..60]), + ranging_offset: to_u32(&buf[60..64]), + ranging_fom: buf[65], + rssi: buf[66], + }) + } +} + /// 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)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PollIndication { /// addressing mode used - pub addr_mode: u8, + pub addr_mode: AddressMode, /// Poll requester address pub request_address: MacAddress, } + +impl ParseableMacEvent for PollIndication { + const SIZE: usize = 9; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + let addr_mode = AddressMode::try_from(buf[0])?; + let request_address = match addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[1], buf[2]]), + AddressMode::Extended => { + MacAddress::Extended([buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]]) + } + }; + + Ok(Self { + addr_mode, + request_address, + }) + } +} diff --git a/embassy-stm32-wpan/src/sub/mac/macros.rs b/embassy-stm32-wpan/src/sub/mac/macros.rs new file mode 100644 index 000000000..1a988a779 --- /dev/null +++ b/embassy-stm32-wpan/src/sub/mac/macros.rs @@ -0,0 +1,32 @@ +#[macro_export] +macro_rules! numeric_enum { + (#[repr($repr:ident)] + $(#$attrs:tt)* $vis:vis enum $name:ident { + $($(#$enum_attrs:tt)* $enum:ident = $constant:expr),* $(,)? + } ) => { + #[repr($repr)] + $(#$attrs)* + $vis enum $name { + $($(#$enum_attrs)* $enum = $constant),* + } + + impl ::core::convert::TryFrom<$repr> for $name { + type Error = (); + + fn try_from(value: $repr) -> ::core::result::Result { + match value { + $($constant => Ok( $name :: $enum ),)* + _ => Err(()) + } + } + } + + impl ::core::convert::From<$name> for $repr { + fn from(value: $name) -> $repr { + match value { + $($name :: $enum => $constant,)* + } + } + } + } +} diff --git a/embassy-stm32-wpan/src/sub/mac/mod.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs index 756d7d5b1..0524f135a 100644 --- a/embassy-stm32-wpan/src/sub/mac/mod.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -9,7 +9,8 @@ use embassy_stm32::ipcc::Ipcc; use embassy_sync::waitqueue::AtomicWaker; use self::commands::MacCommand; -use self::typedefs::MacStatus; +use self::event::MacEvent; +use self::typedefs::MacError; use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::{EvtBox, EvtPacket}; @@ -18,7 +19,10 @@ use crate::{channels, evt}; pub mod commands; mod consts; +pub mod event; +mod helpers; pub mod indications; +mod macros; mod opcodes; pub mod responses; pub mod typedefs; @@ -38,7 +42,7 @@ impl Mac { /// `HW_IPCC_MAC_802_15_4_EvtNot` /// /// This function will stall if the previous `EvtBox` has not been dropped - pub async fn read(&self) -> EvtBox { + pub async fn tl_read(&self) -> EvtBox { // Wait for the last event box to be dropped poll_fn(|cx| { MAC_WAKER.register(cx.waker()); @@ -62,33 +66,20 @@ impl Mac { } /// `HW_IPCC_MAC_802_15_4_CmdEvtNot` - pub async fn write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { - self.write(opcode, payload).await; + pub async fn tl_write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { + self.tl_write(opcode, payload).await; Ipcc::flush(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL).await; unsafe { let p_event_packet = MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket; let p_mac_rsp_evt = &((*p_event_packet).evt_serial.evt.payload) as *const u8; - let evt_serial = (MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket) - .read_volatile() - .evt_serial; - let kind = (evt_serial).kind; - let evt_code = evt_serial.evt.evt_code; - let payload_len = evt_serial.evt.payload_len; - let payload = evt_serial.evt.payload; - - debug!( - "evt kind {} evt_code {} len {} payload {}", - kind, evt_code, payload_len, payload - ); - ptr::read_volatile(p_mac_rsp_evt) } } /// `TL_MAC_802_15_4_SendCmd` - pub async fn write(&self, opcode: u16, payload: &[u8]) { + pub async fn tl_write(&self, opcode: u16, payload: &[u8]) { Ipcc::send(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL, || unsafe { CmdPacket::write_into( MAC_802_15_4_CMD_BUFFER.as_mut_ptr(), @@ -98,37 +89,31 @@ impl Mac { ); }) .await; - - unsafe { - let typ = MAC_802_15_4_CMD_BUFFER.as_ptr().read_volatile().cmdserial.ty; - let cmd_code = MAC_802_15_4_CMD_BUFFER.as_ptr().read_volatile().cmdserial.cmd.cmd_code; - let payload_len = MAC_802_15_4_CMD_BUFFER - .as_ptr() - .read_volatile() - .cmdserial - .cmd - .payload_len; - let payload = MAC_802_15_4_CMD_BUFFER.as_ptr().read_volatile().cmdserial.cmd.payload; - - debug!( - "serial type {} cmd_code {} len {} payload {}", - typ, cmd_code, payload_len, payload - ); - } } - pub async fn send_command(&self, cmd: T) -> Result + pub async fn send_command(&self, cmd: T) -> Result<(), MacError> where T: MacCommand, { let mut payload = [0u8; MAX_PACKET_SIZE]; cmd.copy_into_slice(&mut payload); - debug!("sending {:#x}", payload[..T::SIZE]); + let response = self + .tl_write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]) + .await; - let response = self.write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]).await; + if response == 0x00 { + Ok(()) + } else { + Err(MacError::from(response)) + } + } - MacStatus::try_from(response) + pub async fn read(&self) -> Result { + let evt_box = self.tl_read().await; + let payload = evt_box.payload(); + + MacEvent::try_from(payload) } } diff --git a/embassy-stm32-wpan/src/sub/mac/opcodes.rs b/embassy-stm32-wpan/src/sub/mac/opcodes.rs index 511b78157..c9a07d6af 100644 --- a/embassy-stm32-wpan/src/sub/mac/opcodes.rs +++ b/embassy-stm32-wpan/src/sub/mac/opcodes.rs @@ -25,3 +25,66 @@ pub enum OpcodeM4ToM0 { McpsDataReq = opcode(0x10), McpsPurgeReq = opcode(0x11), } + +pub enum OpcodeM0ToM4 { + MlmeAssociateCnf = 0x00, + MlmeDisassociateCnf, + MlmeGetCnf, + MlmeGtsCnf, + MlmeResetCnf, + MlmeRxEnableCnf, + MlmeScanCnf, + MlmeSetCnf, + MlmeStartCnf, + MlmePollCnf, + MlmeDpsCnf, + MlmeSoundingCnf, + MlmeCalibrateCnf, + McpsDataCnf, + McpsPurgeCnf, + MlmeAssociateInd, + MlmeDisassociateInd, + MlmeBeaconNotifyInd, + MlmeCommStatusInd, + MlmeGtsInd, + MlmeOrphanInd, + MlmeSyncLossInd, + MlmeDpsInd, + McpsDataInd, + MlmePollInd, +} + +impl TryFrom for OpcodeM0ToM4 { + type Error = (); + + fn try_from(value: u16) -> Result { + match value { + 0 => Ok(Self::MlmeAssociateCnf), + 1 => Ok(Self::MlmeDisassociateCnf), + 2 => Ok(Self::MlmeGetCnf), + 3 => Ok(Self::MlmeGtsCnf), + 4 => Ok(Self::MlmeResetCnf), + 5 => Ok(Self::MlmeRxEnableCnf), + 6 => Ok(Self::MlmeScanCnf), + 7 => Ok(Self::MlmeSetCnf), + 8 => Ok(Self::MlmeStartCnf), + 9 => Ok(Self::MlmePollCnf), + 10 => Ok(Self::MlmeDpsCnf), + 11 => Ok(Self::MlmeSoundingCnf), + 12 => Ok(Self::MlmeCalibrateCnf), + 13 => Ok(Self::McpsDataCnf), + 14 => Ok(Self::McpsPurgeCnf), + 15 => Ok(Self::MlmeAssociateInd), + 16 => Ok(Self::MlmeDisassociateInd), + 17 => Ok(Self::MlmeBeaconNotifyInd), + 18 => Ok(Self::MlmeCommStatusInd), + 19 => Ok(Self::MlmeGtsInd), + 20 => Ok(Self::MlmeOrphanInd), + 21 => Ok(Self::MlmeSyncLossInd), + 22 => Ok(Self::MlmeDpsInd), + 23 => Ok(Self::McpsDataInd), + 24 => Ok(Self::MlmePollInd), + _ => Err(()), + } + } +} diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index 8c30a1823..ce2ca2fb2 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -1,35 +1,50 @@ use super::consts::{MAX_ED_SCAN_RESULTS_SUPPORTED, MAX_PAN_DESC_SUPPORTED, MAX_SOUNDING_LIST_SUPPORTED}; -use super::typedefs::{AddressMode, MacAddress, PanDescriptor}; - -pub trait MacResponse { - const SIZE: usize; - - fn parse(buf: &[u8]) -> Self; -} +use super::event::ParseableMacEvent; +use super::helpers::to_u32; +use super::typedefs::{ + AddressMode, AssociationStatus, KeyIdMode, MacAddress, MacStatus, PanDescriptor, PibId, ScanType, SecurityLevel, +}; /// MLME ASSOCIATE Confirm used to inform of the initiating device whether /// its request to associate was successful or unsuccessful -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateConfirm { /// short address allocated by the coordinator on successful association pub assoc_short_address: [u8; 2], /// status of the association request - pub status: u8, + pub status: AssociationStatus, /// security level to be used - pub security_level: u8, + pub security_level: SecurityLevel, /// the originator of the key to be used pub key_source: [u8; 8], /// the mode used to identify the key to be used - pub key_id_mode: u8, + pub key_id_mode: KeyIdMode, /// the index of the key to be used pub key_index: u8, } +impl ParseableMacEvent for AssociateConfirm { + const SIZE: usize = 16; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + assoc_short_address: [buf[0], buf[1]], + status: AssociationStatus::try_from(buf[2])?, + security_level: SecurityLevel::try_from(buf[3])?, + key_source: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], + key_id_mode: KeyIdMode::try_from(buf[12])?, + key_index: buf[13], + }) + } +} + /// MLME DISASSOCIATE Confirm used to send disassociation Confirmation to the application. -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DisassociateConfirm { /// status of the disassociation attempt - pub status: u8, + pub status: MacStatus, /// device addressing mode used pub device_addr_mode: AddressMode, /// the identifier of the PAN of the device @@ -38,51 +53,130 @@ pub struct DisassociateConfirm { pub device_address: MacAddress, } +impl ParseableMacEvent for DisassociateConfirm { + const SIZE: usize = 12; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + let device_addr_mode = AddressMode::try_from(buf[1])?; + let device_address = match device_addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[4], buf[5]]), + AddressMode::Extended => { + MacAddress::Extended([buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]]) + } + }; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + device_addr_mode, + device_pan_id: [buf[2], buf[3]], + device_address, + }) + } +} + /// MLME GET Confirm which requests information about a given PIB attribute -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GetConfirm { /// The pointer to the value of the PIB attribute attempted to read pub pib_attribute_value_ptr: *const u8, /// Status of the GET attempt - pub status: u8, + pub status: MacStatus, /// The name of the PIB attribute attempted to read - pub pib_attribute: u8, + pub pib_attribute: PibId, /// The lenght of the PIB attribute Value return pub pib_attribute_value_len: u8, } +impl ParseableMacEvent for GetConfirm { + const SIZE: usize = 8; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + let address = to_u32(&buf[0..4]); + + Ok(Self { + pib_attribute_value_ptr: address as *const u8, + status: MacStatus::try_from(buf[4])?, + pib_attribute: PibId::try_from(buf[5])?, + pib_attribute_value_len: buf[6], + }) + } +} + /// MLME GTS Confirm which eports the results of a request to allocate a new GTS /// or to deallocate an existing GTS -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsConfirm { /// The characteristics of the GTS pub gts_characteristics: u8, /// The status of the GTS reques - pub status: u8, + pub status: MacStatus, +} + +impl ParseableMacEvent for GtsConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + gts_characteristics: buf[0], + status: MacStatus::try_from(buf[1])?, + }) + } } /// MLME RESET Confirm which is used to report the results of the reset operation -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ResetConfirm { /// The result of the reset operation - status: u8, + status: MacStatus, +} + +impl ParseableMacEvent for ResetConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + }) + } } /// MLME RX ENABLE Confirm which is used to report the results of the attempt /// to enable or disable the receiver -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct RxEnableConfirm { /// Result of the request to enable or disable the receiver - status: u8, + status: MacStatus, +} + +impl ParseableMacEvent for RxEnableConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + }) + } } /// MLME SCAN Confirm which is used to report the result of the channel scan request -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ScanConfirm { /// Status of the scan request - pub status: u8, + pub status: MacStatus, /// The type of scan performed - pub scan_type: u8, + pub scan_type: ScanType, /// Channel page on which the scan was performed pub channel_page: u8, /// Channels given in the request which were not scanned @@ -99,44 +193,124 @@ pub struct ScanConfirm { pub uwb_energy_detect_list: [u8; MAX_ED_SCAN_RESULTS_SUPPORTED], } +impl ParseableMacEvent for ScanConfirm { + const SIZE: usize = 9; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + todo!() + } +} + /// MLME SET Confirm which reports the result of an attempt to write a value to a PIB attribute -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SetConfirm { /// The result of the set operation - pub status: u8, + pub status: MacStatus, /// The name of the PIB attribute that was written - pub pin_attribute: u8, + pub pin_attribute: PibId, +} + +impl ParseableMacEvent for SetConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + pin_attribute: PibId::try_from(buf[1])?, + }) + } } /// MLME START Confirm which is used to report the results of the attempt to /// start using a new superframe configuration -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct StartConfirm { /// Result of the attempt to start using an updated superframe configuration - pub status: u8, + pub status: MacStatus, +} + +impl ParseableMacEvent for StartConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + debug!("{:#x}", buf); + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + }) + } } /// MLME POLL Confirm which is used to report the result of a request to poll the coordinator for data -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PollConfirm { /// The status of the data request - pub status: u8, + pub status: MacStatus, +} + +impl ParseableMacEvent for PollConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + }) + } +} + +/// MLME DPS Confirm which reports the results of the attempt to enable or disable the DPS +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct DpsConfirm { + /// The status of the DPS request + pub status: MacStatus, +} + +impl ParseableMacEvent for DpsConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + }) + } } /// MLME SOUNDING Confirm which reports the result of a request to the PHY to provide /// channel sounding information -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SoundingConfirm { /// Results of the sounding measurement sounding_list: [u8; MAX_SOUNDING_LIST_SUPPORTED], } +impl ParseableMacEvent for SoundingConfirm { + const SIZE: usize = 1; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + let mut sounding_list = [0u8; MAX_SOUNDING_LIST_SUPPORTED]; + sounding_list[..buf.len()].copy_from_slice(buf); + + Ok(Self { sounding_list }) + } +} + /// MLME CALIBRATE Confirm which reports the result of a request to the PHY /// to provide internal propagation path information -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CalibrateConfirm { /// The status of the attempt to return sounding data - pub status: u8, + pub status: MacStatus, /// A count of the propagation time from the ranging counter /// to the transmit antenna pub cal_tx_rmaker_offset: u32, @@ -145,18 +319,33 @@ pub struct CalibrateConfirm { pub cal_rx_rmaker_offset: u32, } +impl ParseableMacEvent for CalibrateConfirm { + const SIZE: usize = 12; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + // 3 byte stuffing + cal_tx_rmaker_offset: to_u32(&buf[4..8]), + cal_rx_rmaker_offset: to_u32(&buf[8..12]), + }) + } +} + /// MCPS DATA Confirm which will be used for reporting the results of /// MAC data related requests from the application -#[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DataConfirm { /// The handle associated with the MSDU being confirmed pub msdu_handle: u8, /// The time, in symbols, at which the data were transmitted - pub a_time_stamp: [u8; 4], + pub time_stamp: [u8; 4], /// ranging status pub ranging_received: u8, /// The status of the last MSDU transmission - pub status: u8, + pub status: MacStatus, /// time units corresponding to an RMARKER at the antenna at /// the beginning of a ranging exchange pub ranging_counter_start: u32, @@ -171,12 +360,45 @@ pub struct DataConfirm { pub ranging_fom: u8, } +impl ParseableMacEvent for DataConfirm { + const SIZE: usize = 28; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + msdu_handle: buf[0], + time_stamp: [buf[1], buf[2], buf[3], buf[4]], + ranging_received: buf[5], + status: MacStatus::try_from(buf[6])?, + ranging_counter_start: to_u32(&buf[7..11]), + ranging_counter_stop: to_u32(&buf[11..15]), + ranging_tracking_interval: to_u32(&buf[15..19]), + ranging_offset: to_u32(&buf[19..23]), + ranging_fom: buf[24], + }) + } +} + /// 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)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PurgeConfirm { /// Handle associated with the MSDU requested to be purged from the transaction queue pub msdu_handle: u8, /// The status of the request - pub status: u8, + pub status: MacStatus, +} + +impl ParseableMacEvent for PurgeConfirm { + const SIZE: usize = 4; + + fn try_parse(buf: &[u8]) -> Result { + Self::validate(buf)?; + + Ok(Self { + msdu_handle: buf[0], + status: MacStatus::try_from(buf[1])?, + }) + } } diff --git a/embassy-stm32-wpan/src/sub/mac/typedefs.rs b/embassy-stm32-wpan/src/sub/mac/typedefs.rs index 7f0dd75c0..fe79b3a79 100644 --- a/embassy-stm32-wpan/src/sub/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/sub/mac/typedefs.rs @@ -1,6 +1,8 @@ +use crate::numeric_enum; + +#[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum MacStatus { - Success = 0x00, +pub enum MacError { Error = 0x01, NotImplemented = 0x02, NotSupported = 0x03, @@ -8,88 +10,115 @@ pub enum MacStatus { Undefined = 0x05, } -impl TryFrom for MacStatus { - type Error = (); - - fn try_from(value: u8) -> Result>::Error> { +impl From for MacError { + fn from(value: u8) -> Self { match value { - 0x00 => Ok(Self::Success), - 0x01 => Ok(Self::Error), - 0x02 => Ok(Self::NotImplemented), - 0x03 => Ok(Self::NotSupported), - 0x04 => Ok(Self::HardwareNotSupported), - 0x05 => Ok(Self::Undefined), - _ => Err(()), + 0x01 => Self::Error, + 0x02 => Self::NotImplemented, + 0x03 => Self::NotSupported, + 0x04 => Self::HardwareNotSupported, + 0x05 => Self::Undefined, + _ => Self::Undefined, } } } -/// this enum contains all the MAC PIB Ids -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum PibId { - // PHY - CurrentChannel = 0x00, - ChannelsSupported = 0x01, - TransmitPower = 0x02, - CCAMode = 0x03, - CurrentPage = 0x04, - MaxFrameDuration = 0x05, - SHRDuration = 0x06, - SymbolsPerOctet = 0x07, - - // MAC - AckWaitDuration = 0x40, - AssociationPermit = 0x41, - AutoRequest = 0x42, - BeaconPayload = 0x45, - BeaconPayloadLength = 0x46, - BeaconOrder = 0x47, - Bsn = 0x49, - CoordExtendedAdddress = 0x4A, - CoordShortAddress = 0x4B, - Dsn = 0x4C, - MaxFrameTotalWaitTime = 0x58, - MaxFrameRetries = 0x59, - PanId = 0x50, - ResponseWaitTime = 0x5A, - RxOnWhenIdle = 0x52, - SecurityEnabled = 0x5D, - ShortAddress = 0x53, - SuperframeOrder = 0x54, - TimestampSupported = 0x5C, - TransactionPersistenceTime = 0x55, - MaxBe = 0x57, - LifsPeriod = 0x5E, - SifsPeriod = 0x5F, - MaxCsmaBackoffs = 0x4E, - MinBe = 0x4F, - PanCoordinator = 0x10, - AssocPanCoordinator = 0x11, - ExtendedAddress = 0x6F, - AclEntryDescriptor = 0x70, - AclEntryDescriptorSize = 0x71, - DefaultSecurity = 0x72, - DefaultSecurityMaterialLength = 0x73, - DefaultSecurityMaterial = 0x74, - DefaultSecuritySuite = 0x75, - SecurityMode = 0x76, - CurrentAclEntries = 0x80, - DefaultSecurityExtendedAddress = 0x81, - AssociatedPanCoordinator = 0x56, - PromiscuousMode = 0x51, +numeric_enum! { + #[repr(u8)] + #[derive(Debug)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum MacStatus { + Success = 0x00, + Error = 0x01, + NotImplemented = 0x02, + NotSupported = 0x03, + HardwareNotSupported = 0x04, + Undefined = 0x05, + } } -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum AddressMode { - NoAddress = 0x00, - Reserved = 0x01, - Short = 0x02, - Extended = 0x03, +numeric_enum! { + #[repr(u8)] + /// this enum contains all the MAC PIB Ids + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum PibId { + // PHY + CurrentChannel = 0x00, + ChannelsSupported = 0x01, + TransmitPower = 0x02, + CCAMode = 0x03, + CurrentPage = 0x04, + MaxFrameDuration = 0x05, + SHRDuration = 0x06, + SymbolsPerOctet = 0x07, + + // MAC + AckWaitDuration = 0x40, + AssociationPermit = 0x41, + AutoRequest = 0x42, + BeaconPayload = 0x45, + BeaconPayloadLength = 0x46, + BeaconOrder = 0x47, + Bsn = 0x49, + CoordExtendedAdddress = 0x4A, + CoordShortAddress = 0x4B, + Dsn = 0x4C, + MaxFrameTotalWaitTime = 0x58, + MaxFrameRetries = 0x59, + PanId = 0x50, + ResponseWaitTime = 0x5A, + RxOnWhenIdle = 0x52, + SecurityEnabled = 0x5D, + ShortAddress = 0x53, + SuperframeOrder = 0x54, + TimestampSupported = 0x5C, + TransactionPersistenceTime = 0x55, + MaxBe = 0x57, + LifsPeriod = 0x5E, + SifsPeriod = 0x5F, + MaxCsmaBackoffs = 0x4E, + MinBe = 0x4F, + PanCoordinator = 0x10, + AssocPanCoordinator = 0x11, + ExtendedAddress = 0x6F, + AclEntryDescriptor = 0x70, + AclEntryDescriptorSize = 0x71, + DefaultSecurity = 0x72, + DefaultSecurityMaterialLength = 0x73, + DefaultSecurityMaterial = 0x74, + DefaultSecuritySuite = 0x75, + SecurityMode = 0x76, + CurrentAclEntries = 0x80, + DefaultSecurityExtendedAddress = 0x81, + AssociatedPanCoordinator = 0x56, + PromiscuousMode = 0x51, + } } -pub union MacAddress { - pub short: [u8; 2], - pub extended: [u8; 8], +numeric_enum! { + #[repr(u8)] + #[derive(Default, Clone, Copy)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum AddressMode { + #[default] + NoAddress = 0x00, + Reserved = 0x01, + Short = 0x02, + Extended = 0x03, +} +} + +#[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum MacAddress { + Short([u8; 2]), + Extended([u8; 8]), +} + +impl Default for MacAddress { + fn default() -> Self { + Self::Short([0, 0]) + } } pub struct GtsCharacteristics { @@ -98,13 +127,15 @@ pub struct GtsCharacteristics { /// MAC PAN Descriptor which contains the network details of the device from /// which the beacon is received +#[derive(Default, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PanDescriptor { /// PAN identifier of the coordinator - pub a_coord_pan_id: [u8; 2], + pub coord_pan_id: [u8; 2], /// Coordinator addressing mode pub coord_addr_mode: AddressMode, /// The current logical channel occupied by the network - pub logical_channel: u8, + pub logical_channel: MacChannel, /// Coordinator address pub coord_addr: MacAddress, /// The current channel page occupied by the network @@ -112,13 +143,179 @@ pub struct PanDescriptor { /// PAN coordinator is accepting GTS requests or not pub gts_permit: bool, /// Superframe specification as specified in the received beacon frame - pub a_superframe_spec: [u8; 2], + pub superframe_spec: [u8; 2], /// The time at which the beacon frame was received, in symbols - pub a_time_stamp: [u8; 4], + pub time_stamp: [u8; 4], /// The LQI at which the network beacon was received pub link_quality: u8, /// Security level purportedly used by the received beacon frame pub security_level: u8, - /// Byte Stuffing to keep 32 bit alignment - pub a_stuffing: [u8; 2], +} + +impl TryFrom<&[u8]> for PanDescriptor { + type Error = (); + + fn try_from(buf: &[u8]) -> Result { + const SIZE: usize = 24; + if buf.len() < SIZE { + return Err(()); + } + + let coord_addr_mode = AddressMode::try_from(buf[2])?; + let coord_addr = match coord_addr_mode { + AddressMode::NoAddress => MacAddress::Short([0, 0]), + AddressMode::Reserved => MacAddress::Short([0, 0]), + AddressMode::Short => MacAddress::Short([buf[4], buf[5]]), + AddressMode::Extended => { + MacAddress::Extended([buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]]) + } + }; + + Ok(Self { + coord_pan_id: [buf[0], buf[1]], + coord_addr_mode, + logical_channel: MacChannel::try_from(buf[3])?, + coord_addr, + channel_page: buf[12], + gts_permit: buf[13] != 0, + superframe_spec: [buf[14], buf[15]], + time_stamp: [buf[16], buf[17], buf[18], buf[19]], + link_quality: buf[20], + security_level: buf[21], + // 2 byte stuffing + }) + } +} + +numeric_enum! { + #[repr(u8)] + #[derive(Default, Clone, Copy)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + /// Building wireless applications with STM32WB series MCUs - Application note 13.10.3 + pub enum MacChannel { + Channel11 = 0x0B, + Channel12 = 0x0C, + Channel13 = 0x0D, + Channel14 = 0x0E, + Channel15 = 0x0F, + #[default] + Channel16 = 0x10, + Channel17 = 0x11, + Channel18 = 0x12, + Channel19 = 0x13, + Channel20 = 0x14, + Channel21 = 0x15, + Channel22 = 0x16, + Channel23 = 0x17, + Channel24 = 0x18, + Channel25 = 0x19, + Channel26 = 0x1A, + } +} + +#[cfg(not(feature = "defmt"))] +bitflags::bitflags! { + pub struct Capabilities: u8 { + /// 1 if the device is capabaleof becoming a PAN coordinator + const IS_COORDINATOR_CAPABLE = 0b00000001; + /// 1 if the device is an FFD, 0 if it is an RFD + const IS_FFD = 0b00000010; + /// 1 if the device is receiving power from mains, 0 if it is battery-powered + const IS_MAINS_POWERED = 0b00000100; + /// 1 if the device does not disable its receiver to conserver power during idle periods + const RECEIVER_ON_WHEN_IDLE = 0b00001000; + // 0b00010000 reserved + // 0b00100000 reserved + /// 1 if the device is capable of sending and receiving secured MAC frames + const IS_SECURE = 0b01000000; + /// 1 if the device wishes the coordinator to allocate a short address as a result of the association + const ALLOCATE_ADDRESS = 0b10000000; + } +} + +#[cfg(feature = "defmt")] +defmt::bitflags! { + pub struct Capabilities: u8 { + /// 1 if the device is capabaleof becoming a PAN coordinator + const IS_COORDINATOR_CAPABLE = 0b00000001; + /// 1 if the device is an FFD, 0 if it is an RFD + const IS_FFD = 0b00000010; + /// 1 if the device is receiving power from mains, 0 if it is battery-powered + const IS_MAINS_POWERED = 0b00000100; + /// 1 if the device does not disable its receiver to conserver power during idle periods + const RECEIVER_ON_WHEN_IDLE = 0b00001000; + // 0b00010000 reserved + // 0b00100000 reserved + /// 1 if the device is capable of sending and receiving secured MAC frames + const IS_SECURE = 0b01000000; + /// 1 if the device wishes the coordinator to allocate a short address as a result of the association + const ALLOCATE_ADDRESS = 0b10000000; + } +} + +numeric_enum! { + #[repr(u8)] + #[derive(Default)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum KeyIdMode { + #[default] + /// the key is determined implicitly from the originator and recipient(s) of the frame + Implicite = 0x00, + /// the key is determined explicitly using a 1 bytes key source and a 1 byte key index + Explicite1Byte = 0x01, + /// the key is determined explicitly using a 4 bytes key source and a 1 byte key index + Explicite4Byte = 0x02, + /// the key is determined explicitly using a 8 bytes key source and a 1 byte key index + Explicite8Byte = 0x03, + } +} + +numeric_enum! { + #[repr(u8)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum AssociationStatus { + /// Association successful + Success = 0x00, + /// PAN at capacity + PanAtCapacity = 0x01, + /// PAN access denied + PanAccessDenied = 0x02 + } +} + +numeric_enum! { + #[repr(u8)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum DisassociationReason { + /// The coordinator wishes the device to leave the PAN. + CoordRequested = 0x01, + /// The device wishes to leave the PAN. + DeviceRequested = 0x02, + } +} + +numeric_enum! { + #[repr(u8)] + #[derive(Default)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum SecurityLevel { + /// MAC Unsecured Mode Security + #[default] + Unsecure = 0x00, + /// MAC ACL Mode Security + AclMode = 0x01, + /// MAC Secured Mode Security + Secured = 0x02, + } +} + +numeric_enum! { + #[repr(u8)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub enum ScanType { + EdScan = 0x00, + Active = 0x01, + Passive = 0x02, + Orphan = 0x03 + } } diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 4100d1ac5..18b29362b 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -7,7 +7,7 @@ use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; use embassy_stm32_wpan::sub::mac::commands::{ResetRequest, SetRequest, StartRequest}; -use embassy_stm32_wpan::sub::mac::typedefs::PibId; +use embassy_stm32_wpan::sub::mac::typedefs::{MacChannel, PibId}; use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -65,109 +65,92 @@ async fn main(spawner: Spawner) { info!("initialized mac: {}", result); info!("resetting"); - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(ResetRequest { set_default_pib: true }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); info!("setting extended address"); let extended_address: u64 = 0xACDE480000000001; - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(SetRequest { pib_attribute_ptr: &extended_address as *const _ as *const u8, pib_attribute: PibId::ExtendedAddress, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); info!("setting short address"); let short_address: u16 = 0x1122; - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(SetRequest { pib_attribute_ptr: &short_address as *const _ as *const u8, pib_attribute: PibId::ShortAddress, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); info!("setting association permit"); let association_permit: bool = true; - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(SetRequest { pib_attribute_ptr: &association_permit as *const _ as *const u8, pib_attribute: PibId::AssociationPermit, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); info!("setting TX power"); let transmit_power: i8 = 2; - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(SetRequest { pib_attribute_ptr: &transmit_power as *const _ as *const u8, pib_attribute: PibId::TransmitPower, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); info!("starting FFD device"); - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(StartRequest { - channel_number: 16, + channel_number: MacChannel::Channel16, beacon_order: 0x0F, superframe_order: 0x0F, pan_coordinator: true, battery_life_extension: false, ..Default::default() }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); info!("setting RX on when idle"); let rx_on_while_idle: bool = true; - let response = mbox - .mac_subsystem + mbox.mac_subsystem .send_command(SetRequest { pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, pib_attribute: PibId::RxOnWhenIdle, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); - // info!("association request"); - // mbox.mac_subsystem - // .send_command(AssociateRequest { - // channel_number: 16, - // channel_page: 0, - // coord_addr_mode: 2, - // coord_address: MacAddress { short: [0x22, 0x11] }, - // capability_information: 0x80, - // coord_pan_id: [0xAA, 0x1A], - // security_level: 0, - - // key_id_mode: 0, - // key_index: 0, - // key_source: [0; 8], - // }) - // .await; - // info!("reading"); - // let result = mbox.mac_subsystem.read().await; - // info!("{}", result.payload()); - - // - // info!("starting ble..."); - // mbox.ble_subsystem.t_write(0x0c, &[]).await; - // - // info!("waiting for ble..."); - // let ble_event = mbox.ble_subsystem.tl_read().await; - // - // info!("ble event: {}", ble_event.payload()); + loop { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt); + } info!("Test OK"); cortex_m::asm::bkpt(); diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index 938fe754f..8042a3704 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -7,7 +7,9 @@ use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, ResetRequest, SetRequest, StartRequest}; -use embassy_stm32_wpan::sub::mac::typedefs::{AddressMode, MacAddress, PibId}; +use embassy_stm32_wpan::sub::mac::typedefs::{ + AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PibId, SecurityLevel, +}; use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -86,14 +88,14 @@ async fn main(spawner: Spawner) { let response = mbox .mac_subsystem .send_command(AssociateRequest { - channel_number: 16, + channel_number: MacChannel::Channel16, channel_page: 0, coord_addr_mode: AddressMode::Short, - coord_address: MacAddress { short: [0x22, 0x11] }, - capability_information: 0x80, + coord_address: MacAddress::Short([0x22, 0x11]), + capability_information: Capabilities::ALLOCATE_ADDRESS, coord_pan_id: [0xAA, 0x1A], - security_level: 0x00, - key_id_mode: 0, + security_level: SecurityLevel::Unsecure, + key_id_mode: KeyIdMode::Implicite, key_source: [0; 8], key_index: 0, }) From eccd2ecebf01753e70705a6ca1e21bc83b2c204c Mon Sep 17 00:00:00 2001 From: goueslati Date: Wed, 12 Jul 2023 16:49:37 +0100 Subject: [PATCH 06/13] change MacAddress to a union instead of an enum --- embassy-stm32-wpan/src/sub/mac/commands.rs | 20 +++- embassy-stm32-wpan/src/sub/mac/indications.rs | 70 ++++++++------ embassy-stm32-wpan/src/sub/mac/mod.rs | 4 +- embassy-stm32-wpan/src/sub/mac/responses.rs | 17 ++-- embassy-stm32-wpan/src/sub/mac/typedefs.rs | 43 ++++++--- examples/stm32wb/src/bin/mac_ffd.rs | 18 ++-- examples/stm32wb/src/bin/mac_rfd.rs | 92 ++++++++++++------- 7 files changed, 168 insertions(+), 96 deletions(-) diff --git a/embassy-stm32-wpan/src/sub/mac/commands.rs b/embassy-stm32-wpan/src/sub/mac/commands.rs index d8a4e3ee1..7ccf10026 100644 --- a/embassy-stm32-wpan/src/sub/mac/commands.rs +++ b/embassy-stm32-wpan/src/sub/mac/commands.rs @@ -9,12 +9,13 @@ pub trait MacCommand { const SIZE: usize; fn copy_into_slice(&self, buf: &mut [u8]) { - unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, 8) }; + unsafe { core::ptr::copy(self as *const _ as *const u8, buf as *mut _ as *mut u8, Self::SIZE) }; } } /// MLME ASSOCIATE Request used to request an association #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateRequest { /// the logical channel on which to attempt association pub channel_number: MacChannel, @@ -45,6 +46,7 @@ impl MacCommand for AssociateRequest { /// MLME DISASSOCIATE Request sed to request a disassociation #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DisassociateRequest { /// device addressing mode used pub device_addr_mode: AddressMode, @@ -73,6 +75,7 @@ impl MacCommand for DisassociateRequest { /// MLME GET Request used to request a PIB value #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GetRequest { /// the name of the PIB attribute to read pub pib_attribute: PibId, @@ -85,6 +88,7 @@ impl MacCommand for GetRequest { /// MLME GTS Request used to request and maintain GTSs #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsRequest { /// the characteristics of the GTS pub characteristics: GtsCharacteristics, @@ -104,6 +108,7 @@ impl MacCommand for GtsRequest { } #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ResetRequest { /// MAC PIB attributes are set to their default values or not during reset pub set_default_pib: bool, @@ -117,6 +122,7 @@ impl MacCommand for ResetRequest { /// MLME RX ENABLE Request used to request that the receiver is either enabled /// for a finite period of time or disabled #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct RxEnableRequest { /// the request operation can be deferred or not pub defer_permit: bool, @@ -148,6 +154,7 @@ impl MacCommand for RxEnableRequest { /// MLME SCAN Request used to initiate a channel scan over a given list of channels #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct ScanRequest { /// the type of scan to be performed pub scan_type: ScanType, @@ -174,6 +181,7 @@ impl MacCommand for ScanRequest { /// MLME SET Request used to attempt to write the given value to the indicated PIB attribute #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SetRequest { /// the pointer to the value of the PIB attribute to set pub pib_attribute_ptr: *const u8, @@ -190,6 +198,7 @@ impl MacCommand for SetRequest { /// configuration #[derive(Default)] #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct StartRequest { /// PAN indentifier to used by the device pub pan_id: [u8; 2], @@ -233,6 +242,7 @@ impl MacCommand for StartRequest { /// MLME SYNC Request used to synchronize with the coordinator by acquiring and, if /// specified, tracking its beacons #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SyncRequest { /// the channel number on which to attempt coordinator synchronization pub channel_number: MacChannel, @@ -252,6 +262,7 @@ impl MacCommand for SyncRequest { /// MLME POLL Request propmts the device to request data from the coordinator #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PollRequest { /// addressing mode of the coordinator pub coord_addr_mode: AddressMode, @@ -277,6 +288,7 @@ impl MacCommand for PollRequest { /// MLME DPS Request allows the next higher layer to request that the PHY utilize a /// given pair of preamble codes for a single use pending expiration of the DPSIndexDuration #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DpsRequest { /// the index value for the transmitter tx_dps_index: u8, @@ -295,6 +307,7 @@ impl MacCommand for DpsRequest { /// MLME SOUNDING request primitive which is used by the next higher layer to request that /// the PHY respond with channel sounding information #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct SoundingRequest; impl MacCommand for SoundingRequest { @@ -305,6 +318,7 @@ impl MacCommand for SoundingRequest { /// MLME CALIBRATE request primitive which used to obtain the results of a ranging /// calibration request from an RDEV #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct CalibrateRequest; impl MacCommand for CalibrateRequest { @@ -314,6 +328,7 @@ impl MacCommand for CalibrateRequest { /// MCPS DATA Request used for MAC data related requests from the application #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct DataRequest { /// the handle assocated with the MSDU to be transmitted pub msdu_ptr: *const u8, @@ -362,6 +377,7 @@ impl MacCommand for DataRequest { /// for MCPS PURGE Request used to purge an MSDU from the transaction queue #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PurgeRequest { /// the handle associated with the MSDU to be purged from the transaction /// queue @@ -375,6 +391,7 @@ impl MacCommand for PurgeRequest { /// MLME ASSOCIATE Response used to initiate a response to an MLME-ASSOCIATE.indication #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateResponse { /// extended address of the device requesting association pub device_address: [u8; 8], @@ -400,6 +417,7 @@ impl MacCommand for AssociateResponse { /// MLME ORPHAN Response used to respond to the MLME ORPHAN Indication #[repr(C)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct OrphanResponse { /// extended address of the orphaned device pub orphan_address: [u8; 8], diff --git a/embassy-stm32-wpan/src/sub/mac/indications.rs b/embassy-stm32-wpan/src/sub/mac/indications.rs index dc5ae4c44..4695f24ef 100644 --- a/embassy-stm32-wpan/src/sub/mac/indications.rs +++ b/embassy-stm32-wpan/src/sub/mac/indications.rs @@ -141,21 +141,25 @@ impl ParseableMacEvent for CommStatusIndication { let dst_addr_mode = AddressMode::try_from(buf[3])?; let src_address = match src_addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[4], buf[5]]), - AddressMode::Extended => { - MacAddress::Extended([buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[4], buf[5]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], + }, }; let dst_address = match dst_addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[12], buf[13]]), - AddressMode::Extended => { - MacAddress::Extended([buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[12], buf[13]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]], + }, }; Ok(Self { @@ -358,22 +362,26 @@ impl ParseableMacEvent for DataIndication { let src_addr_mode = AddressMode::try_from(buf[4])?; let src_address = match src_addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[7], buf[8]]), - AddressMode::Extended => { - MacAddress::Extended([buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[7], buf[8]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14]], + }, }; let dst_addr_mode = AddressMode::try_from(buf[15])?; let dst_address = match dst_addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[18], buf[19]]), - AddressMode::Extended => { - MacAddress::Extended([buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], buf[24], buf[25]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[18], buf[19]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], buf[24], buf[25]], + }, }; Ok(Self { @@ -424,12 +432,14 @@ impl ParseableMacEvent for PollIndication { let addr_mode = AddressMode::try_from(buf[0])?; let request_address = match addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[1], buf[2]]), - AddressMode::Extended => { - MacAddress::Extended([buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[1], buf[2]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]], + }, }; Ok(Self { diff --git a/embassy-stm32-wpan/src/sub/mac/mod.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs index 0524f135a..26358bf81 100644 --- a/embassy-stm32-wpan/src/sub/mac/mod.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -91,13 +91,15 @@ impl Mac { .await; } - pub async fn send_command(&self, cmd: T) -> Result<(), MacError> + pub async fn send_command(&self, cmd: &T) -> Result<(), MacError> where T: MacCommand, { let mut payload = [0u8; MAX_PACKET_SIZE]; cmd.copy_into_slice(&mut payload); + debug!("sending {}", &payload[..T::SIZE]); + let response = self .tl_write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]) .await; diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index ce2ca2fb2..37271ec28 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -27,6 +27,8 @@ impl ParseableMacEvent for AssociateConfirm { const SIZE: usize = 16; fn try_parse(buf: &[u8]) -> Result { + debug!("{}", buf); + Self::validate(buf)?; Ok(Self { @@ -61,12 +63,14 @@ impl ParseableMacEvent for DisassociateConfirm { let device_addr_mode = AddressMode::try_from(buf[1])?; let device_address = match device_addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[4], buf[5]]), - AddressMode::Extended => { - MacAddress::Extended([buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[4], buf[5]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], + }, }; Ok(Self { @@ -238,7 +242,6 @@ impl ParseableMacEvent for StartConfirm { fn try_parse(buf: &[u8]) -> Result { Self::validate(buf)?; - debug!("{:#x}", buf); Ok(Self { status: MacStatus::try_from(buf[0])?, diff --git a/embassy-stm32-wpan/src/sub/mac/typedefs.rs b/embassy-stm32-wpan/src/sub/mac/typedefs.rs index fe79b3a79..1a4c30cbc 100644 --- a/embassy-stm32-wpan/src/sub/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/sub/mac/typedefs.rs @@ -109,18 +109,32 @@ numeric_enum! { } #[derive(Clone, Copy)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum MacAddress { - Short([u8; 2]), - Extended([u8; 8]), +pub union MacAddress { + pub short: [u8; 2], + pub extended: [u8; 8], +} + +#[cfg(feature = "defmt")] +impl defmt::Format for MacAddress { + fn format(&self, fmt: defmt::Formatter) { + unsafe { + defmt::write!( + fmt, + "MacAddress {{ short: {}, extended: {} }}", + self.short, + self.extended + ) + } + } } impl Default for MacAddress { fn default() -> Self { - Self::Short([0, 0]) + Self { short: [0, 0] } } } +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsCharacteristics { pub fields: u8, } @@ -163,12 +177,14 @@ impl TryFrom<&[u8]> for PanDescriptor { let coord_addr_mode = AddressMode::try_from(buf[2])?; let coord_addr = match coord_addr_mode { - AddressMode::NoAddress => MacAddress::Short([0, 0]), - AddressMode::Reserved => MacAddress::Short([0, 0]), - AddressMode::Short => MacAddress::Short([buf[4], buf[5]]), - AddressMode::Extended => { - MacAddress::Extended([buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]]) - } + AddressMode::NoAddress => MacAddress { short: [0, 0] }, + AddressMode::Reserved => MacAddress { short: [0, 0] }, + AddressMode::Short => MacAddress { + short: [buf[4], buf[5]], + }, + AddressMode::Extended => MacAddress { + extended: [buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]], + }, }; Ok(Self { @@ -255,7 +271,7 @@ defmt::bitflags! { numeric_enum! { #[repr(u8)] - #[derive(Default)] + #[derive(Default, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum KeyIdMode { #[default] @@ -285,6 +301,7 @@ numeric_enum! { numeric_enum! { #[repr(u8)] + #[derive(Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DisassociationReason { /// The coordinator wishes the device to leave the PAN. @@ -296,7 +313,7 @@ numeric_enum! { numeric_enum! { #[repr(u8)] - #[derive(Default)] + #[derive(Default, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum SecurityLevel { /// MAC Unsecured Mode Security diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 18b29362b..4e2578a21 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -66,7 +66,7 @@ async fn main(spawner: Spawner) { info!("resetting"); mbox.mac_subsystem - .send_command(ResetRequest { set_default_pib: true }) + .send_command(&ResetRequest { set_default_pib: true }) .await .unwrap(); let evt = mbox.mac_subsystem.read().await; @@ -75,7 +75,7 @@ async fn main(spawner: Spawner) { info!("setting extended address"); let extended_address: u64 = 0xACDE480000000001; mbox.mac_subsystem - .send_command(SetRequest { + .send_command(&SetRequest { pib_attribute_ptr: &extended_address as *const _ as *const u8, pib_attribute: PibId::ExtendedAddress, }) @@ -87,7 +87,7 @@ async fn main(spawner: Spawner) { info!("setting short address"); let short_address: u16 = 0x1122; mbox.mac_subsystem - .send_command(SetRequest { + .send_command(&SetRequest { pib_attribute_ptr: &short_address as *const _ as *const u8, pib_attribute: PibId::ShortAddress, }) @@ -99,7 +99,7 @@ async fn main(spawner: Spawner) { info!("setting association permit"); let association_permit: bool = true; mbox.mac_subsystem - .send_command(SetRequest { + .send_command(&SetRequest { pib_attribute_ptr: &association_permit as *const _ as *const u8, pib_attribute: PibId::AssociationPermit, }) @@ -111,7 +111,7 @@ async fn main(spawner: Spawner) { info!("setting TX power"); let transmit_power: i8 = 2; mbox.mac_subsystem - .send_command(SetRequest { + .send_command(&SetRequest { pib_attribute_ptr: &transmit_power as *const _ as *const u8, pib_attribute: PibId::TransmitPower, }) @@ -122,7 +122,8 @@ async fn main(spawner: Spawner) { info!("starting FFD device"); mbox.mac_subsystem - .send_command(StartRequest { + .send_command(&StartRequest { + pan_id: [0xAA, 0x1A], channel_number: MacChannel::Channel16, beacon_order: 0x0F, superframe_order: 0x0F, @@ -138,7 +139,7 @@ async fn main(spawner: Spawner) { info!("setting RX on when idle"); let rx_on_while_idle: bool = true; mbox.mac_subsystem - .send_command(SetRequest { + .send_command(&SetRequest { pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, pib_attribute: PibId::RxOnWhenIdle, }) @@ -151,7 +152,4 @@ async fn main(spawner: Spawner) { let evt = mbox.mac_subsystem.read().await; defmt::info!("{:#x}", evt); } - - info!("Test OK"); - cortex_m::asm::bkpt(); } diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index 8042a3704..e5f8d54c9 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -6,7 +6,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, ResetRequest, SetRequest, StartRequest}; +use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, GetRequest, ResetRequest, SetRequest}; +use embassy_stm32_wpan::sub::mac::event::MacEvent; use embassy_stm32_wpan::sub::mac::typedefs::{ AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PibId, SecurityLevel, }; @@ -67,52 +68,75 @@ async fn main(spawner: Spawner) { info!("initialized mac: {}", result); info!("resetting"); - let response = mbox - .mac_subsystem - .send_command(ResetRequest { set_default_pib: true }) - .await; - info!("{}", response); + mbox.mac_subsystem + .send_command(&ResetRequest { set_default_pib: true }) + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); info!("setting extended address"); let extended_address: u64 = 0xACDE480000000002; - let response = mbox - .mac_subsystem - .send_command(SetRequest { + mbox.mac_subsystem + .send_command(&SetRequest { pib_attribute_ptr: &extended_address as *const _ as *const u8, pib_attribute: PibId::ExtendedAddress, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + + info!("getting extended address"); + mbox.mac_subsystem + .send_command(&GetRequest { + pib_attribute: PibId::ExtendedAddress, + }) + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + + if let Ok(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) }; + + info!("value {:#x}", value) + } + } info!("assocation request"); - let response = mbox - .mac_subsystem - .send_command(AssociateRequest { - channel_number: MacChannel::Channel16, - channel_page: 0, - coord_addr_mode: AddressMode::Short, - coord_address: MacAddress::Short([0x22, 0x11]), - capability_information: Capabilities::ALLOCATE_ADDRESS, - coord_pan_id: [0xAA, 0x1A], - security_level: SecurityLevel::Unsecure, - key_id_mode: KeyIdMode::Implicite, - key_source: [0; 8], - key_index: 0, - }) - .await; - info!("{}", response); + let a = AssociateRequest { + channel_number: MacChannel::Channel16, + channel_page: 0, + coord_addr_mode: AddressMode::Short, + coord_address: MacAddress { short: [34, 17] }, + capability_information: Capabilities::ALLOCATE_ADDRESS, + coord_pan_id: [0xAA, 0x1A], + security_level: SecurityLevel::Unsecure, + key_id_mode: KeyIdMode::Implicite, + key_source: [0; 8], + key_index: 152, + }; + info!("{}", a); + mbox.mac_subsystem.send_command(&a).await.unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); info!("setting short address"); let short: u64 = 0xACDE480000000002; - let response = mbox - .mac_subsystem - .send_command(SetRequest { + mbox.mac_subsystem + .send_command(&SetRequest { pib_attribute_ptr: &short as *const _ as *const u8, pib_attribute: PibId::ShortAddress, }) - .await; - info!("{}", response); + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); - info!("Test OK"); - cortex_m::asm::bkpt(); + loop { + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + } } From 3f0c8bafb060fdf81a677f0ec37d4db11e732266 Mon Sep 17 00:00:00 2001 From: goueslati Date: Thu, 13 Jul 2023 15:20:50 +0100 Subject: [PATCH 07/13] make it work, disgustingly --- embassy-stm32-wpan/src/sub/mac/commands.rs | 42 +++++++++++++++---- embassy-stm32-wpan/src/sub/mac/consts.rs | 2 +- embassy-stm32-wpan/src/sub/mac/indications.rs | 27 ++++++------ embassy-stm32-wpan/src/sub/mac/opcodes.rs | 2 + embassy-stm32-wpan/src/sub/mac/responses.rs | 7 ++-- embassy-stm32-wpan/src/sub/mac/typedefs.rs | 26 ++++++++---- examples/stm32wb/src/bin/mac_ffd.rs | 30 +++++++++++-- examples/stm32wb/src/bin/mac_rfd.rs | 38 ++++++++++++++--- 8 files changed, 133 insertions(+), 41 deletions(-) diff --git a/embassy-stm32-wpan/src/sub/mac/commands.rs b/embassy-stm32-wpan/src/sub/mac/commands.rs index 7ccf10026..8cfa0a054 100644 --- a/embassy-stm32-wpan/src/sub/mac/commands.rs +++ b/embassy-stm32-wpan/src/sub/mac/commands.rs @@ -1,7 +1,7 @@ use super::opcodes::OpcodeM4ToM0; use super::typedefs::{ - AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, PibId, - ScanType, SecurityLevel, + AddressMode, Capabilities, DisassociationReason, GtsCharacteristics, KeyIdMode, MacAddress, MacChannel, MacStatus, + PanId, PibId, ScanType, SecurityLevel, }; pub trait MacCommand { @@ -26,7 +26,7 @@ pub struct AssociateRequest { /// operational capabilities of the associating device pub capability_information: Capabilities, /// the identifier of the PAN with which to associate - pub coord_pan_id: [u8; 2], + pub coord_pan_id: PanId, /// the security level to be used pub security_level: SecurityLevel, /// the mode used to identify the key to be used @@ -51,7 +51,7 @@ pub struct DisassociateRequest { /// device addressing mode used pub device_addr_mode: AddressMode, /// the identifier of the PAN of the device - pub device_pan_id: [u8; 2], + pub device_pan_id: PanId, /// the reason for the disassociation pub disassociation_reason: DisassociationReason, /// device address @@ -201,7 +201,7 @@ impl MacCommand for SetRequest { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct StartRequest { /// PAN indentifier to used by the device - pub pan_id: [u8; 2], + pub pan_id: PanId, /// logical channel on which to begin pub channel_number: MacChannel, /// channel page on which to begin @@ -277,7 +277,7 @@ pub struct PollRequest { /// originator of the key to be used pub key_source: [u8; 8], /// PAN identifier of the coordinator - pub coord_pan_id: [u8; 2], + pub coord_pan_id: PanId, } impl MacCommand for PollRequest { @@ -337,7 +337,7 @@ pub struct DataRequest { /// destination addressing mode used pub dst_addr_mode: AddressMode, /// destination PAN Id - pub dst_pan_id: [u8; 2], + pub dst_pan_id: PanId, /// destination address pub dst_address: MacAddress, /// the number of octets contained in the MSDU @@ -370,6 +370,31 @@ pub struct DataRequest { pub datrate: u8, } +impl Default for DataRequest { + fn default() -> Self { + Self { + msdu_ptr: 0 as *const u8, + src_addr_mode: AddressMode::NoAddress, + dst_addr_mode: AddressMode::NoAddress, + dst_pan_id: PanId([0, 0]), + dst_address: MacAddress { short: [0, 0] }, + msdu_length: 0, + msdu_handle: 0, + ack_tx: 0, + gts_tx: false, + indirect_tx: 0, + security_level: SecurityLevel::Unsecure, + key_id_mode: KeyIdMode::Implicite, + key_index: 0, + key_source: [0u8; 8], + uwbprf: 0, + ranging: 0, + uwb_preamble_symbol_repetitions: 0, + datrate: 0, + } + } +} + impl MacCommand for DataRequest { const OPCODE: OpcodeM4ToM0 = OpcodeM4ToM0::McpsDataReq; const SIZE: usize = 40; @@ -391,6 +416,7 @@ impl MacCommand for PurgeRequest { /// MLME ASSOCIATE Response used to initiate a response to an MLME-ASSOCIATE.indication #[repr(C)] +#[derive(Default)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct AssociateResponse { /// extended address of the device requesting association @@ -399,7 +425,7 @@ pub struct AssociateResponse { /// association pub assoc_short_address: [u8; 2], /// status of the association attempt - pub status: u8, + pub status: MacStatus, /// security level to be used pub security_level: SecurityLevel, /// the originator of the key to be used diff --git a/embassy-stm32-wpan/src/sub/mac/consts.rs b/embassy-stm32-wpan/src/sub/mac/consts.rs index 892d533b4..56903d980 100644 --- a/embassy-stm32-wpan/src/sub/mac/consts.rs +++ b/embassy-stm32-wpan/src/sub/mac/consts.rs @@ -1,4 +1,4 @@ -pub const MAX_ED_SCAN_RESULTS_SUPPORTED: usize = 16; pub const MAX_PAN_DESC_SUPPORTED: usize = 6; pub const MAX_SOUNDING_LIST_SUPPORTED: usize = 6; pub const MAX_PENDING_ADDRESS: usize = 7; +pub const MAX_ED_SCAN_RESULTS_SUPPORTED: usize = 16; diff --git a/embassy-stm32-wpan/src/sub/mac/indications.rs b/embassy-stm32-wpan/src/sub/mac/indications.rs index 4695f24ef..b67f0a686 100644 --- a/embassy-stm32-wpan/src/sub/mac/indications.rs +++ b/embassy-stm32-wpan/src/sub/mac/indications.rs @@ -3,7 +3,7 @@ use super::event::ParseableMacEvent; use super::helpers::to_u32; use super::typedefs::{ AddressMode, Capabilities, DisassociationReason, KeyIdMode, MacAddress, MacChannel, MacStatus, PanDescriptor, - SecurityLevel, + PanId, SecurityLevel, }; /// MLME ASSOCIATE Indication which will be used by the MAC @@ -110,7 +110,7 @@ impl ParseableMacEvent for BeaconNotifyIndication { pub struct CommStatusIndication { /// The 16-bit PAN identifier of the device from which the frame /// was received or to which the frame was being sent - pub pan_id: [u8; 2], + pub pan_id: PanId, /// Source addressing mode pub src_addr_mode: AddressMode, /// Destination addressing mode @@ -163,7 +163,7 @@ impl ParseableMacEvent for CommStatusIndication { }; Ok(Self { - pan_id: [buf[0], buf[1]], + pan_id: PanId([buf[0], buf[1]]), src_addr_mode, dst_addr_mode, src_address, @@ -251,7 +251,7 @@ impl ParseableMacEvent for OrphanIndication { #[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 - pub pan_id: [u8; 2], + pub pan_id: PanId, /// The reason that synchronization was lost pub loss_reason: u8, /// The logical channel on which the device lost synchronization or to whi @@ -275,7 +275,7 @@ impl ParseableMacEvent for SyncLossIndication { Self::validate(buf)?; Ok(Self { - pan_id: [buf[0], buf[1]], + pan_id: PanId([buf[0], buf[1]]), loss_reason: buf[2], channel_number: MacChannel::try_from(buf[3])?, channel_page: buf[4], @@ -303,19 +303,20 @@ impl ParseableMacEvent for DpsIndication { } #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(C, align(8))] pub struct DataIndication { /// Pointer to the set of octets forming the MSDU being indicated pub msdu_ptr: *const u8, /// Source addressing mode used pub src_addr_mode: AddressMode, /// Source PAN ID - pub src_pan_id: [u8; 2], + pub src_pan_id: PanId, /// Source address pub src_address: MacAddress, /// Destination addressing mode used pub dst_addr_mode: AddressMode, /// Destination PAN ID - pub dst_pan_id: [u8; 2], + pub dst_pan_id: PanId, /// Destination address pub dst_address: MacAddress, /// The number of octets contained in the MSDU being indicated @@ -355,7 +356,7 @@ pub struct DataIndication { } impl ParseableMacEvent for DataIndication { - const SIZE: usize = 72; + const SIZE: usize = 68; fn try_parse(buf: &[u8]) -> Result { Self::validate(buf)?; @@ -387,24 +388,24 @@ impl ParseableMacEvent for DataIndication { Ok(Self { msdu_ptr: to_u32(&buf[0..4]) as *const u8, src_addr_mode, - src_pan_id: [buf[5], buf[6]], + src_pan_id: PanId([buf[5], buf[6]]), src_address, dst_addr_mode, - dst_pan_id: [buf[16], buf[17]], + dst_pan_id: PanId([buf[16], buf[17]]), dst_address, msdu_length: buf[26], mpdu_link_quality: buf[27], dsn: buf[28], time_stamp: [buf[29], buf[30], buf[31], buf[32]], - security_level: SecurityLevel::try_from(buf[33])?, - key_id_mode: KeyIdMode::try_from(buf[34])?, + security_level: SecurityLevel::try_from(buf[33]).unwrap_or(SecurityLevel::Unsecure), // TODO: this is totaly wrong, but I'm too smol brain to fix it + key_id_mode: KeyIdMode::try_from(buf[34]).unwrap_or(KeyIdMode::Implicite), // TODO: this is totaly wrong, but I'm too smol brain to fix it key_source: [buf[35], buf[36], buf[37], buf[38], buf[39], buf[40], buf[41], buf[42]], key_index: buf[43], uwbprf: buf[44], uwn_preamble_symbol_repetitions: buf[45], datrate: buf[46], ranging_received: buf[47], - ranging_counter_start: to_u32(&buf[58..52]), + ranging_counter_start: to_u32(&buf[48..52]), ranging_counter_stop: to_u32(&buf[52..56]), ranging_tracking_interval: to_u32(&buf[56..60]), ranging_offset: to_u32(&buf[60..64]), diff --git a/embassy-stm32-wpan/src/sub/mac/opcodes.rs b/embassy-stm32-wpan/src/sub/mac/opcodes.rs index c9a07d6af..fd7011873 100644 --- a/embassy-stm32-wpan/src/sub/mac/opcodes.rs +++ b/embassy-stm32-wpan/src/sub/mac/opcodes.rs @@ -5,6 +5,7 @@ const fn opcode(ocf: u16) -> isize { ((ST_VENDOR_OGF << 9) | (MAC_802_15_4_CMD_OPCODE_OFFSET + ocf)) as isize } +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum OpcodeM4ToM0 { MlmeAssociateReq = opcode(0x00), MlmeAssociateRes = opcode(0x01), @@ -26,6 +27,7 @@ pub enum OpcodeM4ToM0 { McpsPurgeReq = opcode(0x11), } +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum OpcodeM0ToM4 { MlmeAssociateCnf = 0x00, MlmeDisassociateCnf, diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index 37271ec28..2b90ccdc6 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -2,7 +2,8 @@ use super::consts::{MAX_ED_SCAN_RESULTS_SUPPORTED, MAX_PAN_DESC_SUPPORTED, MAX_S use super::event::ParseableMacEvent; use super::helpers::to_u32; use super::typedefs::{ - AddressMode, AssociationStatus, KeyIdMode, MacAddress, MacStatus, PanDescriptor, PibId, ScanType, SecurityLevel, + AddressMode, AssociationStatus, KeyIdMode, MacAddress, MacStatus, PanDescriptor, PanId, PibId, ScanType, + SecurityLevel, }; /// MLME ASSOCIATE Confirm used to inform of the initiating device whether @@ -50,7 +51,7 @@ pub struct DisassociateConfirm { /// device addressing mode used pub device_addr_mode: AddressMode, /// the identifier of the PAN of the device - pub device_pan_id: [u8; 2], + pub device_pan_id: PanId, /// device address pub device_address: MacAddress, } @@ -76,7 +77,7 @@ impl ParseableMacEvent for DisassociateConfirm { Ok(Self { status: MacStatus::try_from(buf[0])?, device_addr_mode, - device_pan_id: [buf[2], buf[3]], + device_pan_id: PanId([buf[2], buf[3]]), device_address, }) } diff --git a/embassy-stm32-wpan/src/sub/mac/typedefs.rs b/embassy-stm32-wpan/src/sub/mac/typedefs.rs index 1a4c30cbc..5ff051c97 100644 --- a/embassy-stm32-wpan/src/sub/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/sub/mac/typedefs.rs @@ -25,15 +25,12 @@ impl From for MacError { numeric_enum! { #[repr(u8)] - #[derive(Debug)] + #[derive(Debug, Default)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum MacStatus { + #[default] Success = 0x00, - Error = 0x01, - NotImplemented = 0x02, - NotSupported = 0x03, - HardwareNotSupported = 0x04, - Undefined = 0x05, + Failure = 0xFF } } @@ -134,6 +131,10 @@ impl Default for MacAddress { } } +impl MacAddress { + pub const BROADCAST: Self = Self { short: [0xFF, 0xFF] }; +} + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsCharacteristics { pub fields: u8, @@ -145,7 +146,7 @@ pub struct GtsCharacteristics { #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PanDescriptor { /// PAN identifier of the coordinator - pub coord_pan_id: [u8; 2], + pub coord_pan_id: PanId, /// Coordinator addressing mode pub coord_addr_mode: AddressMode, /// The current logical channel occupied by the network @@ -188,7 +189,7 @@ impl TryFrom<&[u8]> for PanDescriptor { }; Ok(Self { - coord_pan_id: [buf[0], buf[1]], + coord_pan_id: PanId([buf[0], buf[1]]), coord_addr_mode, logical_channel: MacChannel::try_from(buf[3])?, coord_addr, @@ -336,3 +337,12 @@ numeric_enum! { Orphan = 0x03 } } + +/// newtype for Pan Id +#[derive(Default, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct PanId(pub [u8; 2]); + +impl PanId { + pub const BROADCAST: Self = Self([0xFF, 0xFF]); +} diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 4e2578a21..37d36fcdd 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -6,8 +6,9 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::sub::mac::commands::{ResetRequest, SetRequest, StartRequest}; -use embassy_stm32_wpan::sub::mac::typedefs::{MacChannel, PibId}; +use embassy_stm32_wpan::sub::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest}; +use embassy_stm32_wpan::sub::mac::event::MacEvent; +use embassy_stm32_wpan::sub::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel}; use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -123,7 +124,7 @@ async fn main(spawner: Spawner) { info!("starting FFD device"); mbox.mac_subsystem .send_command(&StartRequest { - pan_id: [0xAA, 0x1A], + pan_id: PanId([0x1A, 0xAA]), channel_number: MacChannel::Channel16, beacon_order: 0x0F, superframe_order: 0x0F, @@ -151,5 +152,28 @@ async fn main(spawner: Spawner) { loop { let evt = mbox.mac_subsystem.read().await; defmt::info!("{:#x}", evt); + + if let Ok(evt) = evt { + match evt { + MacEvent::MlmeAssociateInd(association) => mbox + .mac_subsystem + .send_command(&AssociateResponse { + device_address: association.device_address, + assoc_short_address: [0x33, 0x44], + status: MacStatus::Success, + security_level: SecurityLevel::Unsecure, + ..Default::default() + }) + .await + .unwrap(), + MacEvent::McpsDataInd(data_ind) => { + let data_addr = data_ind.msdu_ptr; + let mut a = [0u8; 256]; + unsafe { data_addr.copy_to(&mut a as *mut _, data_ind.msdu_length as usize) } + info!("{}", a[..data_ind.msdu_length as usize]) + } + _ => {} + } + } } } diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index e5f8d54c9..756709132 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -6,10 +6,10 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, GetRequest, ResetRequest, SetRequest}; +use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, DataRequest, GetRequest, ResetRequest, SetRequest}; use embassy_stm32_wpan::sub::mac::event::MacEvent; use embassy_stm32_wpan::sub::mac::typedefs::{ - AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PibId, SecurityLevel, + AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PanId, PibId, SecurityLevel, }; use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; @@ -112,7 +112,7 @@ async fn main(spawner: Spawner) { coord_addr_mode: AddressMode::Short, coord_address: MacAddress { short: [34, 17] }, capability_information: Capabilities::ALLOCATE_ADDRESS, - coord_pan_id: [0xAA, 0x1A], + coord_pan_id: PanId([0x1A, 0xAA]), security_level: SecurityLevel::Unsecure, key_id_mode: KeyIdMode::Implicite, key_source: [0; 8], @@ -123,11 +123,16 @@ async fn main(spawner: Spawner) { let evt = mbox.mac_subsystem.read().await; info!("{:#x}", evt); + let short_addr = if let Ok(MacEvent::MlmeAssociateCnf(conf)) = evt { + conf.assoc_short_address + } else { + defmt::panic!() + }; + info!("setting short address"); - let short: u64 = 0xACDE480000000002; mbox.mac_subsystem .send_command(&SetRequest { - pib_attribute_ptr: &short as *const _ as *const u8, + pib_attribute_ptr: &short_addr as *const _ as *const u8, pib_attribute: PibId::ShortAddress, }) .await @@ -135,6 +140,29 @@ async fn main(spawner: Spawner) { let evt = mbox.mac_subsystem.read().await; info!("{:#x}", evt); + info!("sending data"); + let mut data_buffer = [0u8; 256]; + let data = b"Hello from embassy!"; + data_buffer[..data.len()].copy_from_slice(data); + mbox.mac_subsystem + .send_command(&DataRequest { + src_addr_mode: AddressMode::Short, + dst_addr_mode: AddressMode::Short, + dst_pan_id: PanId::BROADCAST, + dst_address: MacAddress::BROADCAST, + msdu_handle: 0x02, + ack_tx: 0x00, + gts_tx: false, + msdu_ptr: &data_buffer as *const _ as *const u8, + msdu_length: data.len() as u8, + security_level: SecurityLevel::Unsecure, + ..Default::default() + }) + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + loop { let evt = mbox.mac_subsystem.read().await; info!("{:#x}", evt); From 68792bb9188b69c1e7629425a0d39110c602b9b2 Mon Sep 17 00:00:00 2001 From: goueslati Date: Thu, 13 Jul 2023 15:48:15 +0100 Subject: [PATCH 08/13] final structs unchecked --- embassy-stm32-wpan/src/sub/mac/indications.rs | 23 ++++++++++++-- embassy-stm32-wpan/src/sub/mac/responses.rs | 31 +++++++++++++++++-- embassy-stm32-wpan/src/sub/mac/typedefs.rs | 17 +++++++++- 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/embassy-stm32-wpan/src/sub/mac/indications.rs b/embassy-stm32-wpan/src/sub/mac/indications.rs index b67f0a686..6df4aa23a 100644 --- a/embassy-stm32-wpan/src/sub/mac/indications.rs +++ b/embassy-stm32-wpan/src/sub/mac/indications.rs @@ -96,12 +96,31 @@ pub struct BeaconNotifyIndication { } impl ParseableMacEvent for BeaconNotifyIndication { - const SIZE: usize = 12; + const SIZE: usize = 88; fn try_parse(buf: &[u8]) -> Result { + // TODO: this is unchecked + Self::validate(buf)?; - todo!() + let addr_list = [ + MacAddress::try_from(&buf[26..34])?, + MacAddress::try_from(&buf[34..42])?, + MacAddress::try_from(&buf[42..50])?, + MacAddress::try_from(&buf[50..58])?, + MacAddress::try_from(&buf[58..66])?, + MacAddress::try_from(&buf[66..74])?, + MacAddress::try_from(&buf[74..82])?, + ]; + + Ok(Self { + sdu_ptr: to_u32(&buf[0..4]) as *const u8, + pan_descriptor: PanDescriptor::try_from(&buf[4..26])?, + addr_list, + bsn: buf[82], + pend_addr_spec: buf[83], + sdu_length: buf[83], + }) } } diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index 2b90ccdc6..0d3c09869 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -199,12 +199,39 @@ pub struct ScanConfirm { } impl ParseableMacEvent for ScanConfirm { - const SIZE: usize = 9; + const SIZE: usize = 185; fn try_parse(buf: &[u8]) -> Result { + // TODO: this is unchecked + Self::validate(buf)?; - todo!() + let mut energy_detect_list = [0; MAX_ED_SCAN_RESULTS_SUPPORTED]; + energy_detect_list.copy_from_slice(&buf[8..24]); + + let pan_descriptor_list = [ + PanDescriptor::try_from(&buf[24..46])?, + PanDescriptor::try_from(&buf[46..68])?, + PanDescriptor::try_from(&buf[68..90])?, + PanDescriptor::try_from(&buf[90..102])?, + PanDescriptor::try_from(&buf[102..124])?, + PanDescriptor::try_from(&buf[124..146])?, + ]; + + let mut uwb_energy_detect_list = [0; MAX_ED_SCAN_RESULTS_SUPPORTED]; + uwb_energy_detect_list.copy_from_slice(&buf[147..163]); + + Ok(Self { + status: MacStatus::try_from(buf[0])?, + scan_type: ScanType::try_from(buf[1])?, + channel_page: buf[2], + unscanned_channels: [buf[3], buf[4], buf[5], buf[6]], + result_list_size: buf[7], + energy_detect_list, + pan_descriptor_list, + detected_category: buf[146], + uwb_energy_detect_list, + }) } } diff --git a/embassy-stm32-wpan/src/sub/mac/typedefs.rs b/embassy-stm32-wpan/src/sub/mac/typedefs.rs index 5ff051c97..30c7731b2 100644 --- a/embassy-stm32-wpan/src/sub/mac/typedefs.rs +++ b/embassy-stm32-wpan/src/sub/mac/typedefs.rs @@ -135,6 +135,21 @@ impl MacAddress { pub const BROADCAST: Self = Self { short: [0xFF, 0xFF] }; } +impl TryFrom<&[u8]> for MacAddress { + type Error = (); + + fn try_from(buf: &[u8]) -> Result { + const SIZE: usize = 8; + if buf.len() < SIZE { + return Err(()); + } + + Ok(Self { + extended: [buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]], + }) + } +} + #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct GtsCharacteristics { pub fields: u8, @@ -171,7 +186,7 @@ impl TryFrom<&[u8]> for PanDescriptor { type Error = (); fn try_from(buf: &[u8]) -> Result { - const SIZE: usize = 24; + const SIZE: usize = 22; if buf.len() < SIZE { return Err(()); } From f90b170dad91848d5a0ff746d873bd8a4ce7e91f Mon Sep 17 00:00:00 2001 From: goueslati Date: Thu, 13 Jul 2023 16:29:29 +0100 Subject: [PATCH 09/13] cleanup --- embassy-stm32-wpan/Cargo.toml | 2 +- embassy-stm32-wpan/src/sub/mac/mod.rs | 2 -- embassy-stm32-wpan/src/sub/mac/responses.rs | 2 -- embassy-stm32-wpan/src/sub/sys.rs | 8 ++++---- examples/stm32wb/.cargo/config.toml | 4 ++-- examples/stm32wb/src/bin/mac_ffd.rs | 10 +++++++--- examples/stm32wb/src/bin/mac_rfd.rs | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 1325faed9..91540321f 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -29,7 +29,7 @@ stm32wb-hci = { version = "0.1.2", features = ["version-5-0"], optional = true } bitflags = { version = "2.3.3", optional = true } [features] -default = ["stm32wb55rg", "mac", "ble", "defmt"] +default = [] defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] ble = ["dep:stm32wb-hci"] diff --git a/embassy-stm32-wpan/src/sub/mac/mod.rs b/embassy-stm32-wpan/src/sub/mac/mod.rs index 26358bf81..ab39f89c2 100644 --- a/embassy-stm32-wpan/src/sub/mac/mod.rs +++ b/embassy-stm32-wpan/src/sub/mac/mod.rs @@ -98,8 +98,6 @@ impl Mac { let mut payload = [0u8; MAX_PACKET_SIZE]; cmd.copy_into_slice(&mut payload); - debug!("sending {}", &payload[..T::SIZE]); - let response = self .tl_write_and_get_response(T::OPCODE as u16, &payload[..T::SIZE]) .await; diff --git a/embassy-stm32-wpan/src/sub/mac/responses.rs b/embassy-stm32-wpan/src/sub/mac/responses.rs index 0d3c09869..2f6f5bf58 100644 --- a/embassy-stm32-wpan/src/sub/mac/responses.rs +++ b/embassy-stm32-wpan/src/sub/mac/responses.rs @@ -28,8 +28,6 @@ impl ParseableMacEvent for AssociateConfirm { const SIZE: usize = 16; fn try_parse(buf: &[u8]) -> Result { - debug!("{}", buf); - Self::validate(buf)?; Ok(Self { diff --git a/embassy-stm32-wpan/src/sub/sys.rs b/embassy-stm32-wpan/src/sub/sys.rs index caa4845f2..c17fd531d 100644 --- a/embassy-stm32-wpan/src/sub/sys.rs +++ b/embassy-stm32-wpan/src/sub/sys.rs @@ -50,7 +50,7 @@ impl Sys { } /// `HW_IPCC_SYS_CmdEvtNot` - pub async fn write_and_get_response(&self, opcode: ShciOpcode, payload: &[u8]) -> SchiCommandStatus { + pub async fn write_and_get_response(&self, opcode: ShciOpcode, payload: &[u8]) -> Result { self.write(opcode, payload).await; Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await; @@ -59,12 +59,12 @@ impl Sys { let p_command_event = &((*p_event_packet).evt_serial.evt.payload) as *const _ as *const CcEvt; let p_payload = &((*p_command_event).payload) as *const u8; - ptr::read_volatile(p_payload).try_into().unwrap() + ptr::read_volatile(p_payload).try_into() } } #[cfg(feature = "mac")] - pub async fn shci_c2_mac_802_15_4_init(&self) -> SchiCommandStatus { + pub async fn shci_c2_mac_802_15_4_init(&self) -> Result { use crate::tables::{ Mac802_15_4Table, TracesTable, MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, TL_MAC_802_15_4_TABLE, TL_TRACES_TABLE, TRACES_EVT_QUEUE, @@ -88,7 +88,7 @@ impl Sys { } #[cfg(feature = "ble")] - pub async fn shci_c2_ble_init(&self, param: ShciBleInitCmdParam) -> SchiCommandStatus { + pub async fn shci_c2_ble_init(&self, param: ShciBleInitCmdParam) -> Result { self.write_and_get_response(ShciOpcode::BleInit, param.payload()).await } diff --git a/examples/stm32wb/.cargo/config.toml b/examples/stm32wb/.cargo/config.toml index cf62a10a0..51c499ee7 100644 --- a/examples/stm32wb/.cargo/config.toml +++ b/examples/stm32wb/.cargo/config.toml @@ -1,7 +1,7 @@ [target.'cfg(all(target_arch = "arm", target_os = "none"))'] # replace STM32WB55CCUx with your chip as listed in `probe-rs chip list` -runner = "probe-run --chip STM32WB55RGVx --speed 1000 --connect-under-reset" -# runner = "teleprobe local run --chip STM32WB55RG --elf" +# runner = "probe-run --chip STM32WB55RGVx --speed 1000 --connect-under-reset" +runner = "teleprobe local run --chip STM32WB55RG --elf" [build] target = "thumbv7em-none-eabihf" diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 37d36fcdd..689a28353 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -168,9 +168,13 @@ async fn main(spawner: Spawner) { .unwrap(), MacEvent::McpsDataInd(data_ind) => { let data_addr = data_ind.msdu_ptr; - let mut a = [0u8; 256]; - unsafe { data_addr.copy_to(&mut a as *mut _, data_ind.msdu_length as usize) } - info!("{}", a[..data_ind.msdu_length as usize]) + let mut data = [0u8; 256]; + unsafe { data_addr.copy_to(&mut data as *mut _, data_ind.msdu_length as usize) } + info!("{}", data[..data_ind.msdu_length as usize]); + + if &data[..data_ind.msdu_length as usize] == b"Hello from embassy!" { + info!("success"); + } } _ => {} } diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index 756709132..ea349f9a8 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -148,7 +148,7 @@ async fn main(spawner: Spawner) { .send_command(&DataRequest { src_addr_mode: AddressMode::Short, dst_addr_mode: AddressMode::Short, - dst_pan_id: PanId::BROADCAST, + dst_pan_id: PanId([0x1A, 0xAA]), dst_address: MacAddress::BROADCAST, msdu_handle: 0x02, ack_tx: 0x00, From d6dd5ea5d3ab7309bd5b4bec28afaee68d20b4ae Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 14:19:32 -0500 Subject: [PATCH 10/13] revert toolchain changes --- rust-toolchain.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index bad6d3a42..179ed1d6a 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,8 +1,8 @@ # Before upgrading check that everything is available on all tier1 targets here: # https://rust-lang.github.io/rustup-components-history [toolchain] -channel = "nightly" -components = [ "rust-src", "rustfmt", "llvm-tools" ] +channel = "nightly-2023-06-28" +components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] targets = [ "thumbv7em-none-eabi", "thumbv7m-none-eabi", @@ -11,4 +11,4 @@ targets = [ "thumbv8m.main-none-eabihf", "riscv32imac-unknown-none-elf", "wasm32-unknown-unknown", -] +] \ No newline at end of file From d11a94e2a7c030dac7a7c4d6967f614104111d5a Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 14:28:42 -0500 Subject: [PATCH 11/13] wpan: add mac test --- tests/stm32/Cargo.toml | 20 ++-- tests/stm32/src/bin/rtc.rs | 2 + .../stm32/src/bin/{tl_mbox.rs => wpan_ble.rs} | 2 +- tests/stm32/src/bin/wpan_mac.rs | 108 ++++++++++++++++++ 4 files changed, 124 insertions(+), 8 deletions(-) rename tests/stm32/src/bin/{tl_mbox.rs => wpan_ble.rs} (99%) create mode 100644 tests/stm32/src/bin/wpan_mac.rs diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index d94bd730b..b3a805e5a 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -12,14 +12,15 @@ stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo -stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble" ] # Nucleo +stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "mac" ] # Nucleo stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board sdmmc = [] chrono = ["embassy-stm32/chrono", "dep:chrono"] can = [] -ble = ["dep:embassy-stm32-wpan"] +ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"] +mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"] not-gpdma = [] [dependencies] @@ -48,11 +49,6 @@ chrono = { version = "^0.4", default-features = false, optional = true} # BEGIN TESTS # Generated by gen_test.py. DO NOT EDIT. -[[bin]] -name = "tl_mbox" -path = "src/bin/tl_mbox.rs" -required-features = [ "ble",] - [[bin]] name = "can" path = "src/bin/can.rs" @@ -103,6 +99,16 @@ name = "usart_rx_ringbuffered" path = "src/bin/usart_rx_ringbuffered.rs" required-features = [ "not-gpdma",] +[[bin]] +name = "wpan_ble" +path = "src/bin/wpan_ble.rs" +required-features = [ "ble",] + +[[bin]] +name = "wpan_mac" +path = "src/bin/wpan_mac.rs" +required-features = [ "mac",] + # END TESTS [profile.dev] diff --git a/tests/stm32/src/bin/rtc.rs b/tests/stm32/src/bin/rtc.rs index 582df5753..194b153d5 100644 --- a/tests/stm32/src/bin/rtc.rs +++ b/tests/stm32/src/bin/rtc.rs @@ -1,3 +1,5 @@ +// required-features: chrono + #![no_std] #![no_main] #![feature(type_alias_impl_trait)] diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/wpan_ble.rs similarity index 99% rename from tests/stm32/src/bin/tl_mbox.rs rename to tests/stm32/src/bin/wpan_ble.rs index af3832709..3ad8aca4e 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/wpan_ble.rs @@ -64,7 +64,7 @@ async fn main(spawner: Spawner) { version_major, version_minor, subversion, sram2a_size, sram2b_size ); - mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; + let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; info!("resetting BLE..."); mbox.ble_subsystem.reset().await; diff --git a/tests/stm32/src/bin/wpan_mac.rs b/tests/stm32/src/bin/wpan_mac.rs new file mode 100644 index 000000000..d97a4d404 --- /dev/null +++ b/tests/stm32/src/bin/wpan_mac.rs @@ -0,0 +1,108 @@ +// required-features: mac + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +#[path = "../common.rs"] +mod common; + +use common::*; +use embassy_executor::Spawner; +use embassy_stm32::bind_interrupts; +use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32_wpan::sub::mac::commands::{AssociateRequest, GetRequest, ResetRequest, SetRequest}; +use embassy_stm32_wpan::sub::mac::event::MacEvent; +use embassy_stm32_wpan::sub::mac::typedefs::{ + AddressMode, Capabilities, KeyIdMode, MacAddress, MacChannel, PanId, PibId, SecurityLevel, +}; +use embassy_stm32_wpan::sub::mm; +use embassy_stm32_wpan::TlMbox; +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::main] +async fn main(spawner: Spawner) { + let p = embassy_stm32::init(config()); + 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 }) + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + + info!("setting extended address"); + let extended_address: u64 = 0xACDE480000000002; + mbox.mac_subsystem + .send_command(&SetRequest { + pib_attribute_ptr: &extended_address as *const _ as *const u8, + pib_attribute: PibId::ExtendedAddress, + }) + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + + info!("getting extended address"); + mbox.mac_subsystem + .send_command(&GetRequest { + pib_attribute: PibId::ExtendedAddress, + }) + .await + .unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + + if let Ok(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) }; + + info!("value {:#x}", value) + } + } + + info!("assocation request"); + let a = AssociateRequest { + channel_number: MacChannel::Channel16, + channel_page: 0, + coord_addr_mode: AddressMode::Short, + coord_address: MacAddress { short: [34, 17] }, + capability_information: Capabilities::ALLOCATE_ADDRESS, + coord_pan_id: PanId([0x1A, 0xAA]), + security_level: SecurityLevel::Unsecure, + key_id_mode: KeyIdMode::Implicite, + key_source: [0; 8], + key_index: 152, + }; + info!("{}", a); + mbox.mac_subsystem.send_command(&a).await.unwrap(); + let evt = mbox.mac_subsystem.read().await; + info!("{:#x}", evt); + + info!("Test OK"); + cortex_m::asm::bkpt(); +} From 1f63fdbb15b2f8fb94167e12428901357de15c11 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 14:31:35 -0500 Subject: [PATCH 12/13] stm32/tests: fix cargo --- tests/stm32/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index b3a805e5a..3007cd1e6 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -21,6 +21,7 @@ chrono = ["embassy-stm32/chrono", "dep:chrono"] can = [] ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"] mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"] +embassy-stm32-wpan = [] not-gpdma = [] [dependencies] From 3705b4f40d206490a5165a287791206ac70573d9 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 15 Jul 2023 14:38:02 -0500 Subject: [PATCH 13/13] rustfmt --- examples/stm32wb/src/bin/eddystone_beacon.rs | 2 +- examples/stm32wb/src/bin/gatt_server.rs | 2 +- examples/stm32wb/src/bin/tl_mbox_ble.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/stm32wb/src/bin/eddystone_beacon.rs b/examples/stm32wb/src/bin/eddystone_beacon.rs index b99f8cb2e..451bd7d29 100644 --- a/examples/stm32wb/src/bin/eddystone_beacon.rs +++ b/examples/stm32wb/src/bin/eddystone_beacon.rs @@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) { let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); - mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; + let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; info!("resetting BLE..."); mbox.ble_subsystem.reset().await; diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs index 7621efb11..0f6419d45 100644 --- a/examples/stm32wb/src/bin/gatt_server.rs +++ b/examples/stm32wb/src/bin/gatt_server.rs @@ -71,7 +71,7 @@ async fn main(_spawner: Spawner) { let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); - mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; + let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; info!("resetting BLE..."); mbox.ble_subsystem.reset().await; diff --git a/examples/stm32wb/src/bin/tl_mbox_ble.rs b/examples/stm32wb/src/bin/tl_mbox_ble.rs index a511e89aa..90349422e 100644 --- a/examples/stm32wb/src/bin/tl_mbox_ble.rs +++ b/examples/stm32wb/src/bin/tl_mbox_ble.rs @@ -49,7 +49,7 @@ async fn main(_spawner: Spawner) { let sys_event = mbox.sys_subsystem.read().await; info!("sys event: {}", sys_event.payload()); - mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; + let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; info!("starting ble..."); mbox.ble_subsystem.tl_write(0x0c, &[]).await;