From 08125aa919a4dc4de79f91de9a7f3586e51a7739 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sun, 23 Nov 2025 13:11:18 -0600 Subject: wpan: restructure ipcc and hil test wpan_mac --- ci.sh | 2 +- embassy-stm32-wpan/src/channels.rs | 15 +- embassy-stm32-wpan/src/lib.rs | 46 +++-- embassy-stm32-wpan/src/mac/commands.rs | 9 +- embassy-stm32-wpan/src/mac/control.rs | 4 +- embassy-stm32-wpan/src/mac/driver.rs | 6 +- embassy-stm32-wpan/src/mac/event.rs | 6 +- embassy-stm32-wpan/src/mac/runner.rs | 12 +- embassy-stm32-wpan/src/shci.rs | 134 +++++++------- embassy-stm32-wpan/src/sub/ble.rs | 85 +++++---- embassy-stm32-wpan/src/sub/mac.rs | 144 ++++++++------- embassy-stm32-wpan/src/sub/mm.rs | 37 ++-- embassy-stm32-wpan/src/sub/sys.rs | 82 +++++---- embassy-stm32-wpan/src/tables.rs | 50 +++--- embassy-stm32/src/ipcc.rs | 250 ++++++++++++++++----------- examples/stm32wb/src/bin/eddystone_beacon.rs | 116 ++++++------- examples/stm32wb/src/bin/gatt_server.rs | 118 ++++++------- examples/stm32wb/src/bin/mac_ffd.rs | 47 +++-- examples/stm32wb/src/bin/mac_ffd_net.rs | 9 +- examples/stm32wb/src/bin/mac_rfd.rs | 40 ++--- examples/stm32wb/src/bin/tl_mbox.rs | 2 +- examples/stm32wb/src/bin/tl_mbox_ble.rs | 21 ++- examples/stm32wb/src/bin/tl_mbox_mac.rs | 12 +- tests/stm32/src/bin/wpan_ble.rs | 120 ++++++------- tests/stm32/src/bin/wpan_mac.rs | 29 ++-- 25 files changed, 736 insertions(+), 660 deletions(-) diff --git a/ci.sh b/ci.sh index 6cc2a031d..b4ed0dc18 100755 --- a/ci.sh +++ b/ci.sh @@ -35,7 +35,7 @@ rm -rf out/tests/nrf5340-dk # disabled because these boards are not on the shelf rm -rf out/tests/mspm0g3507 -rm out/tests/stm32wb55rg/wpan_mac +# rm out/tests/stm32wb55rg/wpan_mac rm out/tests/stm32wb55rg/wpan_ble # unstable, I think it's running out of RAM? diff --git a/embassy-stm32-wpan/src/channels.rs b/embassy-stm32-wpan/src/channels.rs index 9a2be1cfa..58f857136 100644 --- a/embassy-stm32-wpan/src/channels.rs +++ b/embassy-stm32-wpan/src/channels.rs @@ -48,9 +48,20 @@ //! |<----HW_IPCC_TRACES_CHANNEL----------------------| //! | | //! +//! + +#[repr(u8)] +pub enum IpccChannel { + Channel1 = 1, + Channel2 = 2, + Channel3 = 3, + Channel4 = 4, + Channel5 = 5, + Channel6 = 6, +} pub mod cpu1 { - use embassy_stm32::ipcc::IpccChannel; + use super::IpccChannel; pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1; pub const IPCC_SYSTEM_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel2; @@ -70,7 +81,7 @@ pub mod cpu1 { } pub mod cpu2 { - use embassy_stm32::ipcc::IpccChannel; + use super::IpccChannel; pub const IPCC_BLE_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel1; pub const IPCC_SYSTEM_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel2; diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index f6b1f6021..18b0feada 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -26,7 +26,7 @@ use core::sync::atomic::{Ordering, compiler_fence}; use embassy_hal_internal::Peri; use embassy_stm32::interrupt; -use embassy_stm32::ipcc::{Config, Ipcc, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32::ipcc::{Config, Ipcc, IpccRxChannel, ReceiveInterruptHandler, TransmitInterruptHandler}; use embassy_stm32::peripherals::IPCC; use sub::mm::MemoryManager; use sub::sys::Sys; @@ -53,14 +53,13 @@ type PacketHeader = LinkedListNode; /// Transport Layer for the Mailbox interface pub struct TlMbox<'d> { - _ipcc: Peri<'d, IPCC>, - - pub sys_subsystem: Sys, - pub mm_subsystem: MemoryManager, + pub sys_subsystem: Sys<'d>, + pub mm_subsystem: MemoryManager<'d>, #[cfg(feature = "ble")] - pub ble_subsystem: sub::ble::Ble, + pub ble_subsystem: sub::ble::Ble<'d>, #[cfg(feature = "mac")] - pub mac_subsystem: sub::mac::Mac, + pub mac_subsystem: sub::mac::Mac<'d>, + pub traces: IpccRxChannel<'d>, } impl<'d> TlMbox<'d> { @@ -92,7 +91,7 @@ impl<'d> TlMbox<'d> { /// be handled by `TL_BLE_Init`; see Figure 66). This completes the procedure laid out in /// Figure 66. // TODO: document what the user should do after calling init to use the mac_802_15_4 subsystem - pub fn init( + pub async fn init( ipcc: Peri<'d, IPCC>, _irqs: impl interrupt::typelevel::Binding + interrupt::typelevel::Binding, @@ -185,16 +184,35 @@ impl<'d> TlMbox<'d> { compiler_fence(Ordering::SeqCst); // this is equivalent to `HW_IPCC_Enable`, which is called by `TL_Enable` - Ipcc::enable(config); + let [ + (_hw_ipcc_ble_cmd_channel, _ipcc_ble_event_channel), + (ipcc_system_cmd_rsp_channel, ipcc_system_event_channel), + (_ipcc_mac_802_15_4_cmd_rsp_channel, _ipcc_mac_802_15_4_notification_ack_channel), + (ipcc_mm_release_buffer_channel, _ipcc_traces_channel), + (_ipcc_ble_lld_cmd_channel, _ipcc_ble_lld_rsp_channel), + (_ipcc_hci_acl_data_channel, _), + ] = Ipcc::new(ipcc, _irqs, config).split(); + + let mm = sub::mm::MemoryManager::new(ipcc_mm_release_buffer_channel); + let mut sys = sub::sys::Sys::new(ipcc_system_cmd_rsp_channel, ipcc_system_event_channel); + + debug!("sys event: {}", sys.read().await.payload()); Self { - _ipcc: ipcc, - sys_subsystem: sub::sys::Sys::new(), + sys_subsystem: sys, #[cfg(feature = "ble")] - ble_subsystem: sub::ble::Ble::new(), + ble_subsystem: sub::ble::Ble::new( + _hw_ipcc_ble_cmd_channel, + _ipcc_ble_event_channel, + _ipcc_hci_acl_data_channel, + ), #[cfg(feature = "mac")] - mac_subsystem: sub::mac::Mac::new(), - mm_subsystem: sub::mm::MemoryManager::new(), + mac_subsystem: sub::mac::Mac::new( + _ipcc_mac_802_15_4_cmd_rsp_channel, + _ipcc_mac_802_15_4_notification_ack_channel, + ), + mm_subsystem: mm, + traces: _ipcc_traces_channel, } } } diff --git a/embassy-stm32-wpan/src/mac/commands.rs b/embassy-stm32-wpan/src/mac/commands.rs index a3a40f377..d96f0094a 100644 --- a/embassy-stm32-wpan/src/mac/commands.rs +++ b/embassy-stm32-wpan/src/mac/commands.rs @@ -393,9 +393,14 @@ impl<'a, T: AsRef<[u8]>> TryFrom> for DataRequest { dst_pan_id: frame.dst_pan_id().ok_or(())?.into(), dst_address: frame.dst_addr().ok_or(())?.into(), msdu_handle: frame.sequence_number().ok_or(())?, - ack_tx: 0x00, + key_source: frame.key_source().unwrap_or_default().try_into().unwrap_or_default(), + ack_tx: frame.ack_request() as u8, gts_tx: false, - security_level: SecurityLevel::Unsecure, + security_level: if frame.security_enabled() { + SecurityLevel::Secured + } else { + SecurityLevel::Unsecure + }, ..Default::default() }; diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs index d2a7b65ee..14c6fdd2b 100644 --- a/embassy-stm32-wpan/src/mac/control.rs +++ b/embassy-stm32-wpan/src/mac/control.rs @@ -20,7 +20,7 @@ use crate::sub::mac::MacTx; pub struct Control<'a> { rx_event_channel: &'a ZeroCopyPubSub>, - mac_tx: &'a Mutex, + mac_tx: &'a Mutex>, #[allow(unused)] network_state: &'a blocking_mutex::Mutex>, } @@ -28,7 +28,7 @@ pub struct Control<'a> { impl<'a> Control<'a> { pub(crate) fn new( rx_event_channel: &'a ZeroCopyPubSub>, - mac_tx: &'a Mutex, + mac_tx: &'a Mutex>, network_state: &'a blocking_mutex::Mutex>, ) -> Self { Self { diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs index c43d595b7..41171ce3d 100644 --- a/embassy-stm32-wpan/src/mac/driver.rs +++ b/embassy-stm32-wpan/src/mac/driver.rs @@ -37,8 +37,8 @@ impl NetworkState { } pub struct DriverState<'d> { - pub mac_tx: Mutex, - pub mac_rx: MacRx, + pub mac_tx: Mutex>, + pub mac_rx: MacRx<'d>, pub rx_event_channel: ZeroCopyPubSub>, pub rx_data_channel: Channel, 1>, pub tx_data_channel: Channel, @@ -48,7 +48,7 @@ pub struct DriverState<'d> { } impl<'d> DriverState<'d> { - pub const fn new(mac: Mac) -> Self { + pub const fn new(mac: Mac<'d>) -> Self { let (mac_rx, mac_tx) = mac.split(); let mac_tx = Mutex::new(mac_tx); diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs index 9ca4f5a2a..39856e185 100644 --- a/embassy-stm32-wpan/src/mac/event.rs +++ b/embassy-stm32-wpan/src/mac/event.rs @@ -10,7 +10,7 @@ use super::responses::{ }; use crate::evt::{EvtBox, MemoryManager}; use crate::mac::opcodes::OpcodeM0ToM4; -use crate::sub::mac::{self, Mac}; +use crate::sub::mac::{self, MacRx}; pub(crate) trait ParseableMacEvent: Sized { fn from_buffer<'a>(buf: &'a [u8]) -> Result<&'a Self, ()> { @@ -53,7 +53,7 @@ pub enum MacEvent<'a> { } impl<'a> MacEvent<'a> { - pub(crate) fn new(event_box: EvtBox) -> Result { + pub(crate) fn new(event_box: EvtBox) -> Result { let payload = event_box.payload(); let opcode = u16::from_le_bytes(payload[0..2].try_into().unwrap()); @@ -148,6 +148,6 @@ unsafe impl<'a> Send for MacEvent<'a> {} impl<'a> Drop for MacEvent<'a> { fn drop(&mut self) { - unsafe { mac::Mac::drop_event_packet(ptr::null_mut()) }; + unsafe { mac::MacRx::drop_event_packet(ptr::null_mut()) }; } } diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index acca70019..3b7d895df 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -24,11 +24,11 @@ pub struct Runner<'a> { // therefore, we don't need to worry about overwriting events rx_event_channel: &'a ZeroCopyPubSub>, rx_data_channel: &'a Channel, 1>, - mac_rx: &'a mut MacRx, + mac_rx: Mutex>, tx_data_channel: &'a Channel, tx_buf_channel: &'a Channel, - mac_tx: &'a Mutex, + mac_tx: &'a Mutex>, #[allow(unused)] network_state: &'a blocking_mutex::Mutex>, @@ -38,10 +38,10 @@ impl<'a> Runner<'a> { pub(crate) fn new( rx_event_channel: &'a ZeroCopyPubSub>, rx_data_channel: &'a Channel, 1>, - mac_rx: &'a mut MacRx, + mac_rx: &'a mut MacRx<'a>, tx_data_channel: &'a Channel, tx_buf_channel: &'a Channel, - mac_tx: &'a Mutex, + mac_tx: &'a Mutex>, tx_buf_queue: &'a mut [[u8; MTU]; BUF_SIZE], network_state: &'a blocking_mutex::Mutex>, short_address: [u8; 2], @@ -61,7 +61,7 @@ impl<'a> Runner<'a> { Self { rx_event_channel, rx_data_channel, - mac_rx, + mac_rx: Mutex::new(mac_rx), tx_data_channel, tx_buf_channel, mac_tx, @@ -83,7 +83,7 @@ impl<'a> Runner<'a> { join::join( async { loop { - if let Ok(mac_event) = self.mac_rx.read().await { + if let Ok(mac_event) = self.mac_rx.try_lock().unwrap().read().await { match mac_event { MacEvent::MlmeAssociateCnf(_) | MacEvent::MlmeDisassociateCnf(_) diff --git a/embassy-stm32-wpan/src/shci.rs b/embassy-stm32-wpan/src/shci.rs index 30d689716..1946c55fd 100644 --- a/embassy-stm32-wpan/src/shci.rs +++ b/embassy-stm32-wpan/src/shci.rs @@ -274,69 +274,64 @@ pub struct ShciBleInitCmdParam { pub options: u8, /// Reserved for future use - shall be set to 0 pub hw_version: u8, - // /** - // * Maximum number of connection-oriented channels in initiator mode. - // * Range: 0 .. 64 - // */ - // pub max_coc_initiator_nbr: u8, - // - // /** - // * Minimum transmit power in dBm supported by the Controller. - // * Range: -127 .. 20 - // */ - // pub min_tx_power: i8, - // - // /** - // * Maximum transmit power in dBm supported by the Controller. - // * Range: -127 .. 20 - // */ - // pub max_tx_power: i8, - // - // /** - // * RX model configuration - // * - bit 0: 1: agc_rssi model improved vs RF blockers 0: Legacy agc_rssi model - // * - other bits: reserved ( shall be set to 0) - // */ - // pub rx_model_config: u8, - // - // /* Maximum number of advertising sets. - // * Range: 1 .. 8 with limitation: - // * This parameter is linked to max_adv_data_len such as both compliant with allocated Total memory computed with BLE_EXT_ADV_BUFFER_SIZE based - // * on Max Extended advertising configuration supported. - // * This parameter is considered by the CPU2 when Options has SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV flag set - // */ - // pub max_adv_set_nbr: u8, - // - // /* Maximum advertising data length (in bytes) - // * Range: 31 .. 1650 with limitation: - // * This parameter is linked to max_adv_set_nbr such as both compliant with allocated Total memory computed with BLE_EXT_ADV_BUFFER_SIZE based - // * on Max Extended advertising configuration supported. - // * This parameter is considered by the CPU2 when Options has SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV flag set - // */ - // pub max_adv_data_len: u16, - // - // /* RF TX Path Compensation Value (16-bit signed integer). Units: 0.1 dB. - // * Range: -1280 .. 1280 - // */ - // pub tx_path_compens: i16, - // - // /* RF RX Path Compensation Value (16-bit signed integer). Units: 0.1 dB. - // * Range: -1280 .. 1280 - // */ - // pub rx_path_compens: i16, - // - // /* BLE core specification version (8-bit unsigned integer). - // * values as: 11(5.2), 12(5.3) - // */ - // pub ble_core_version: u8, - // - // /** - // * Options flags extension - // * - bit 0: 1: appearance Writable 0: appearance Read-Only - // * - bit 1: 1: Enhanced ATT supported 0: Enhanced ATT not supported - // * - other bits: reserved ( shall be set to 0) - // */ - // pub options_extension: u8, + /// + /// Maximum number of connection-oriented channels in initiator mode. + /// Range: 0 .. 64 + pub max_coc_initiator_nbr: u8, + + /// + /// Minimum transmit power in dBm supported by the Controller. + /// Range: -127 .. 20 + pub min_tx_power: i8, + + /// + /// Maximum transmit power in dBm supported by the Controller. + /// Range: -127 .. 20 + pub max_tx_power: i8, + + /// + /// RX model configuration + /// - bit 0: 1: agc_rssi model improved vs RF blockers 0: Legacy agc_rssi model + /// - other bits: reserved ( shall be set to 0) + pub rx_model_config: u8, + + /// Maximum number of advertising sets. + /// Range: 1 .. 8 with limitation: + /// This parameter is linked to max_adv_data_len such as both compliant with allocated Total memory computed with BLE_EXT_ADV_BUFFER_SIZE based + /// on Max Extended advertising configuration supported. + /// This parameter is considered by the CPU2 when Options has SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV flag set + pub max_adv_set_nbr: u8, + + /// Maximum advertising data length (in bytes) + /// Range: 31 .. 1650 with limitation: + /// This parameter is linked to max_adv_set_nbr such as both compliant with allocated Total memory computed with BLE_EXT_ADV_BUFFER_SIZE based + /// on Max Extended advertising configuration supported. + /// This parameter is considered by the CPU2 when Options has SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV flag set + pub max_adv_data_len: u16, + + /// RF TX Path Compensation Value (16-bit signed integer). Units: 0.1 dB. + /// Range: -1280 .. 1280 + pub tx_path_compens: i16, + + //// RF RX Path Compensation Value (16-bit signed integer). Units: 0.1 dB. + /// Range: -1280 .. 1280 + pub rx_path_compens: i16, + + /// BLE core specification version (8-bit unsigned integer). + /// values as: 11(5.2), 12(5.3) + pub ble_core_version: u8, + + /// Options flags extension + /// - bit 0: 1: appearance Writable 0: appearance Read-Only + /// - bit 1: 1: Enhanced ATT supported 0: Enhanced ATT not supported + /// - other bits: reserved ( shall be set to 0) + pub options_extension: u8, + + /// MaxAddEattBearers + /// Maximum number of bearers that can be created for Enhanced ATT + /// in addition to the number of links + /// - Range: 0 .. 4 + pub max_add_eatt_bearers: u8, } impl ShciBleInitCmdParam { @@ -351,7 +346,7 @@ impl Default for ShciBleInitCmdParam { p_ble_buffer_address: 0, ble_buffer_size: 0, num_attr_record: 68, - num_attr_serv: 8, + num_attr_serv: 4, attr_value_arr_size: 1344, num_of_links: 2, extended_packet_length_enable: 1, @@ -366,6 +361,17 @@ impl Default for ShciBleInitCmdParam { viterbi_enable: 1, options: 0, hw_version: 0, + max_coc_initiator_nbr: 32, + min_tx_power: -40, + max_tx_power: 6, + rx_model_config: 0, + max_adv_set_nbr: 2, + max_adv_data_len: 1650, + tx_path_compens: 0, + rx_path_compens: 0, + ble_core_version: 11, + options_extension: 0, + max_add_eatt_bearers: 4, } } } diff --git a/embassy-stm32-wpan/src/sub/ble.rs b/embassy-stm32-wpan/src/sub/ble.rs index cd69a0479..d5ed2ca28 100644 --- a/embassy-stm32-wpan/src/sub/ble.rs +++ b/embassy-stm32-wpan/src/sub/ble.rs @@ -1,6 +1,6 @@ use core::ptr; -use embassy_stm32::ipcc::Ipcc; +use embassy_stm32::ipcc::{IpccRxChannel, IpccTxChannel}; use hci::Opcode; use crate::cmd::CmdPacket; @@ -9,7 +9,7 @@ use crate::evt::{EvtBox, EvtPacket, EvtStub}; use crate::sub::mm; use crate::tables::{BLE_CMD_BUFFER, BleTable, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE}; use crate::unsafe_linked_list::LinkedListNode; -use crate::{channels, evt}; +use crate::evt; /// A guard that, once constructed, may be used to send BLE commands to CPU2. /// @@ -36,15 +36,21 @@ use crate::{channels, evt}; /// # mbox.ble_subsystem.reset().await; /// # let _reset_response = mbox.ble_subsystem.read().await; /// ``` -pub struct Ble { - _private: (), +pub struct Ble<'a> { + hw_ipcc_ble_cmd_channel: IpccTxChannel<'a>, + ipcc_ble_event_channel: IpccRxChannel<'a>, + ipcc_hci_acl_data_channel: IpccTxChannel<'a>, } -impl Ble { +impl<'a> Ble<'a> { /// Constructs a guard that allows for BLE commands to be sent to CPU2. /// /// This takes the place of `TL_BLE_Init`, completing that step as laid out in AN5289, Fig 66. - pub(crate) fn new() -> Self { + pub(crate) fn new( + hw_ipcc_ble_cmd_channel: IpccTxChannel<'a>, + ipcc_ble_event_channel: IpccRxChannel<'a>, + ipcc_hci_acl_data_channel: IpccTxChannel<'a>, + ) -> Self { unsafe { LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); @@ -56,44 +62,51 @@ impl Ble { }); } - Self { _private: () } + Self { + hw_ipcc_ble_cmd_channel, + ipcc_ble_event_channel, + ipcc_hci_acl_data_channel, + } } /// `HW_IPCC_BLE_EvtNot` - pub async fn tl_read(&self) -> EvtBox { - Ipcc::receive(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, || unsafe { - if let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) { - Some(EvtBox::new(node_ptr.cast())) - } else { - None - } - }) - .await + pub async fn tl_read(&mut self) -> EvtBox { + self.ipcc_ble_event_channel + .receive(|| unsafe { + if let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) { + Some(EvtBox::new(node_ptr.cast())) + } else { + None + } + }) + .await } /// `TL_BLE_SendCmd` - pub async fn tl_write(&self, opcode: u16, payload: &[u8]) { - Ipcc::send(channels::cpu1::IPCC_BLE_CMD_CHANNEL, || unsafe { - CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload); - }) - .await; + pub async fn tl_write(&mut self, opcode: u16, payload: &[u8]) { + self.hw_ipcc_ble_cmd_channel + .send(|| unsafe { + CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload); + }) + .await; } /// `TL_BLE_SendAclData` - pub async fn acl_write(&self, handle: u16, payload: &[u8]) { - Ipcc::send(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, || unsafe { - CmdPacket::write_into( - HCI_ACL_DATA_BUFFER.as_mut_ptr() as *mut _, - TlPacketType::AclData, - handle, - payload, - ); - }) - .await; + pub async fn acl_write(&mut self, handle: u16, payload: &[u8]) { + self.ipcc_hci_acl_data_channel + .send(|| unsafe { + CmdPacket::write_into( + HCI_ACL_DATA_BUFFER.as_mut_ptr() as *mut _, + TlPacketType::AclData, + handle, + payload, + ); + }) + .await; } } -impl evt::MemoryManager for Ble { +impl<'a> evt::MemoryManager for Ble<'a> { /// SAFETY: passing a pointer to something other than a managed event packet is UB unsafe fn drop_event_packet(evt: *mut EvtPacket) { let stub = unsafe { @@ -110,13 +123,17 @@ impl evt::MemoryManager for Ble { pub extern crate stm32wb_hci as hci; -impl hci::Controller for Ble { +impl<'a> hci::Controller for Ble<'a> { async fn controller_write(&mut self, opcode: Opcode, payload: &[u8]) { self.tl_write(opcode.0, payload).await; } + #[allow(invalid_reference_casting)] async fn controller_read_into(&self, buf: &mut [u8]) { - let evt_box = self.tl_read().await; + // A complete hack since I cannot update the trait + let s = unsafe { &mut *(self as *const _ as *mut Ble) }; + + let evt_box = s.tl_read().await; let evt_serial = evt_box.serial(); buf[..evt_serial.len()].copy_from_slice(evt_serial); diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs index 93cafbc72..ce2903e61 100644 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ b/embassy-stm32-wpan/src/sub/mac.rs @@ -4,67 +4,78 @@ use core::sync::atomic::{AtomicBool, Ordering}; use core::task::Poll; use embassy_futures::poll_once; -use embassy_stm32::ipcc::Ipcc; +use embassy_stm32::ipcc::{Ipcc, IpccRxChannel, IpccTxChannel}; use embassy_sync::waitqueue::AtomicWaker; use crate::cmd::CmdPacket; use crate::consts::TlPacketType; +use crate::evt; use crate::evt::{EvtBox, EvtPacket}; use crate::mac::commands::MacCommand; use crate::mac::event::MacEvent; use crate::mac::typedefs::MacError; use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; -use crate::{channels, evt}; +use crate::unsafe_linked_list::LinkedListNode; static MAC_WAKER: AtomicWaker = AtomicWaker::new(); static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false); -pub struct Mac { - _private: (), +pub struct Mac<'a> { + ipcc_mac_802_15_4_cmd_rsp_channel: IpccTxChannel<'a>, + ipcc_mac_802_15_4_notification_ack_channel: IpccRxChannel<'a>, } -impl Mac { - pub(crate) fn new() -> Self { - Self { _private: () } - } - - pub const fn split(self) -> (MacRx, MacTx) { - (MacRx { _private: () }, MacTx { _private: () }) - } - - pub async fn tl_write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { - MacTx { _private: () }.tl_write_and_get_response(opcode, payload).await - } - - pub async fn tl_write(&self, opcode: u16, payload: &[u8]) { - MacTx { _private: () }.tl_write(opcode, payload).await - } - - pub async fn send_command(&self, cmd: &T) -> Result<(), MacError> - where - T: MacCommand, - { - MacTx { _private: () }.send_command(cmd).await - } +impl<'a> Mac<'a> { + pub(crate) fn new( + ipcc_mac_802_15_4_cmd_rsp_channel: IpccTxChannel<'a>, + ipcc_mac_802_15_4_notification_ack_channel: IpccRxChannel<'a>, + ) -> Self { + use crate::tables::{ + MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, Mac802_15_4Table, TL_MAC_802_15_4_TABLE, + TL_TRACES_TABLE, TRACES_EVT_QUEUE, TracesTable, + }; - pub async fn tl_read(&self) -> EvtBox { - MacRx { _private: () }.tl_read().await + unsafe { + LinkedListNode::init_head(TRACES_EVT_QUEUE.as_mut_ptr() as *mut _); + + TL_TRACES_TABLE.as_mut_ptr().write_volatile(TracesTable { + traces_queue: TRACES_EVT_QUEUE.as_ptr() as *const _, + }); + + TL_MAC_802_15_4_TABLE.as_mut_ptr().write_volatile(Mac802_15_4Table { + p_cmdrsp_buffer: MAC_802_15_4_CMD_BUFFER.as_mut_ptr().cast(), + p_notack_buffer: MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr().cast(), + evt_queue: core::ptr::null_mut(), + }); + }; + + Self { + ipcc_mac_802_15_4_cmd_rsp_channel, + ipcc_mac_802_15_4_notification_ack_channel, + } } - pub async fn read(&self) -> Result, ()> { - MacRx { _private: () }.read().await + pub const fn split(self) -> (MacRx<'a>, MacTx<'a>) { + ( + MacRx { + ipcc_mac_802_15_4_notification_ack_channel: self.ipcc_mac_802_15_4_notification_ack_channel, + }, + MacTx { + ipcc_mac_802_15_4_cmd_rsp_channel: self.ipcc_mac_802_15_4_cmd_rsp_channel, + }, + ) } } -pub struct MacTx { - _private: (), +pub struct MacTx<'a> { + ipcc_mac_802_15_4_cmd_rsp_channel: IpccTxChannel<'a>, } -impl MacTx { +impl<'a> MacTx<'a> { /// `HW_IPCC_MAC_802_15_4_CmdEvtNot` - pub async fn tl_write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { + pub async fn tl_write_and_get_response(&mut 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; + self.ipcc_mac_802_15_4_cmd_rsp_channel.flush().await; unsafe { let p_event_packet = MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket; @@ -75,19 +86,20 @@ impl MacTx { } /// `TL_MAC_802_15_4_SendCmd` - 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(), - TlPacketType::MacCmd, - opcode, - payload, - ); - }) - .await; + pub async fn tl_write(&mut self, opcode: u16, payload: &[u8]) { + self.ipcc_mac_802_15_4_cmd_rsp_channel + .send(|| unsafe { + CmdPacket::write_into( + MAC_802_15_4_CMD_BUFFER.as_mut_ptr(), + TlPacketType::MacCmd, + opcode, + payload, + ); + }) + .await; } - pub async fn send_command(&self, cmd: &T) -> Result<(), MacError> + pub async fn send_command(&mut self, cmd: &T) -> Result<(), MacError> where T: MacCommand, { @@ -101,19 +113,19 @@ impl MacTx { } } -pub struct MacRx { - _private: (), +pub struct MacRx<'a> { + ipcc_mac_802_15_4_notification_ack_channel: IpccRxChannel<'a>, } -impl MacRx { +impl<'a> MacRx<'a> { /// `HW_IPCC_MAC_802_15_4_EvtNot` /// /// This function will stall if the previous `EvtBox` has not been dropped - pub async fn tl_read(&self) -> EvtBox { + pub async fn tl_read(&mut self) -> EvtBox> { // Wait for the last event box to be dropped poll_fn(|cx| { MAC_WAKER.register(cx.waker()); - if MAC_EVT_OUT.load(Ordering::SeqCst) { + if MAC_EVT_OUT.load(Ordering::Acquire) { Poll::Pending } else { Poll::Ready(()) @@ -122,22 +134,23 @@ impl MacRx { .await; // Return a new event box - Ipcc::receive(channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, || unsafe { - // The closure is not async, therefore the closure must execute to completion (cannot be dropped) - // Therefore, the event box is guaranteed to be cleaned up if it's not leaked - MAC_EVT_OUT.store(true, Ordering::SeqCst); - - Some(EvtBox::new(MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _)) - }) - .await + self.ipcc_mac_802_15_4_notification_ack_channel + .receive(|| unsafe { + // The closure is not async, therefore the closure must execute to completion (cannot be dropped) + // Therefore, the event box is guaranteed to be cleaned up if it's not leaked + MAC_EVT_OUT.store(true, Ordering::SeqCst); + + Some(EvtBox::new(MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _)) + }) + .await } - pub async fn read(&self) -> Result, ()> { + pub async fn read<'b>(&mut self) -> Result, ()> { MacEvent::new(self.tl_read().await) } } -impl evt::MemoryManager for Mac { +impl<'a> evt::MemoryManager for MacRx<'a> { /// SAFETY: passing a pointer to something other than a managed event packet is UB unsafe fn drop_event_packet(_: *mut EvtPacket) { trace!("mac drop event"); @@ -151,13 +164,10 @@ impl evt::MemoryManager for Mac { ); // Clear the rx flag - let _ = poll_once(Ipcc::receive::<()>( - channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, - || None, - )); + let _ = poll_once(Ipcc::receive::<()>(3, || None)); // Allow a new read call - MAC_EVT_OUT.store(false, Ordering::SeqCst); + MAC_EVT_OUT.store(false, Ordering::Release); MAC_WAKER.wake(); } } diff --git a/embassy-stm32-wpan/src/sub/mm.rs b/embassy-stm32-wpan/src/sub/mm.rs index a90c6ee55..aac252929 100644 --- a/embassy-stm32-wpan/src/sub/mm.rs +++ b/embassy-stm32-wpan/src/sub/mm.rs @@ -5,26 +5,26 @@ use core::task::Poll; use aligned::{A4, Aligned}; use cortex_m::interrupt; -use embassy_stm32::ipcc::Ipcc; +use embassy_stm32::ipcc::IpccTxChannel; use embassy_sync::waitqueue::AtomicWaker; use crate::consts::POOL_SIZE; +use crate::evt; use crate::evt::EvtPacket; #[cfg(feature = "ble")] use crate::tables::BLE_SPARE_EVT_BUF; use crate::tables::{EVT_POOL, FREE_BUF_QUEUE, MemManagerTable, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE}; use crate::unsafe_linked_list::LinkedListNode; -use crate::{channels, evt}; static MM_WAKER: AtomicWaker = AtomicWaker::new(); static mut LOCAL_FREE_BUF_QUEUE: Aligned> = Aligned(MaybeUninit::uninit()); -pub struct MemoryManager { - _private: (), +pub struct MemoryManager<'a> { + ipcc_mm_release_buffer_channel: IpccTxChannel<'a>, } -impl MemoryManager { - pub(crate) fn new() -> Self { +impl<'a> MemoryManager<'a> { + pub(crate) fn new(ipcc_mm_release_buffer_channel: IpccTxChannel<'a>) -> Self { unsafe { LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); @@ -43,10 +43,12 @@ impl MemoryManager { }); } - Self { _private: () } + Self { + ipcc_mm_release_buffer_channel, + } } - pub async fn run_queue(&self) -> ! { + pub async fn run_queue(&mut self) -> ! { loop { poll_fn(|cx| unsafe { MM_WAKER.register(cx.waker()); @@ -58,20 +60,21 @@ impl MemoryManager { }) .await; - Ipcc::send(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, || { - interrupt::free(|_| unsafe { - // CS required while moving nodes - while let Some(node_ptr) = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { - LinkedListNode::insert_head(FREE_BUF_QUEUE.as_mut_ptr(), node_ptr); - } + self.ipcc_mm_release_buffer_channel + .send(|| { + interrupt::free(|_| unsafe { + // CS required while moving nodes + while let Some(node_ptr) = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { + LinkedListNode::insert_head(FREE_BUF_QUEUE.as_mut_ptr(), node_ptr); + } + }) }) - }) - .await; + .await; } } } -impl evt::MemoryManager for MemoryManager { +impl<'a> evt::MemoryManager for MemoryManager<'a> { /// SAFETY: passing a pointer to something other than a managed event packet is UB unsafe fn drop_event_packet(evt: *mut EvtPacket) { interrupt::free(|_| unsafe { diff --git a/embassy-stm32-wpan/src/sub/sys.rs b/embassy-stm32-wpan/src/sub/sys.rs index 8a3382f86..dffe9942c 100644 --- a/embassy-stm32-wpan/src/sub/sys.rs +++ b/embassy-stm32-wpan/src/sub/sys.rs @@ -1,5 +1,7 @@ use core::ptr; +use embassy_stm32::ipcc::{IpccRxChannel, IpccTxChannel}; + use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::{CcEvt, EvtBox, EvtPacket}; @@ -8,16 +10,20 @@ use crate::shci::{SchiCommandStatus, ShciBleInitCmdParam, ShciOpcode}; use crate::sub::mm; use crate::tables::{SysTable, WirelessFwInfoTable}; use crate::unsafe_linked_list::LinkedListNode; -use crate::{Ipcc, SYS_CMD_BUF, SYSTEM_EVT_QUEUE, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE, channels}; +use crate::{SYS_CMD_BUF, SYSTEM_EVT_QUEUE, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE}; /// A guard that, once constructed, allows for sys commands to be sent to CPU2. -pub struct Sys { - _private: (), +pub struct Sys<'a> { + ipcc_system_cmd_rsp_channel: IpccTxChannel<'a>, + ipcc_system_event_channel: IpccRxChannel<'a>, } -impl Sys { +impl<'a> Sys<'a> { /// TL_Sys_Init - pub(crate) fn new() -> Self { + pub(crate) fn new( + ipcc_system_cmd_rsp_channel: IpccTxChannel<'a>, + ipcc_system_event_channel: IpccRxChannel<'a>, + ) -> Self { unsafe { LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); @@ -27,7 +33,10 @@ impl Sys { }); } - Self { _private: () } + Self { + ipcc_system_cmd_rsp_channel, + ipcc_system_event_channel, + } } /// Returns CPU2 wireless firmware information (if present). @@ -38,17 +47,22 @@ impl Sys { if info.version != 0 { Some(info) } else { None } } - pub async fn write(&self, opcode: ShciOpcode, payload: &[u8]) { - Ipcc::send(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, || unsafe { - CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode as u16, payload); - }) - .await; + pub async fn write(&mut self, opcode: ShciOpcode, payload: &[u8]) { + self.ipcc_system_cmd_rsp_channel + .send(|| unsafe { + CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode as u16, payload); + }) + .await; } /// `HW_IPCC_SYS_CmdEvtNot` - pub async fn write_and_get_response(&self, opcode: ShciOpcode, payload: &[u8]) -> Result { + pub async fn write_and_get_response( + &mut self, + opcode: ShciOpcode, + payload: &[u8], + ) -> Result { self.write(opcode, payload).await; - Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await; + self.ipcc_system_cmd_rsp_channel.flush().await; unsafe { let p_event_packet = SYS_CMD_BUF.as_ptr() as *const EvtPacket; @@ -60,26 +74,7 @@ impl Sys { } #[cfg(feature = "mac")] - pub async fn shci_c2_mac_802_15_4_init(&self) -> Result { - use crate::tables::{ - MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, Mac802_15_4Table, TL_MAC_802_15_4_TABLE, - TL_TRACES_TABLE, TRACES_EVT_QUEUE, TracesTable, - }; - - unsafe { - LinkedListNode::init_head(TRACES_EVT_QUEUE.as_mut_ptr() as *mut _); - - TL_TRACES_TABLE.as_mut_ptr().write_volatile(TracesTable { - traces_queue: TRACES_EVT_QUEUE.as_ptr() as *const _, - }); - - TL_MAC_802_15_4_TABLE.as_mut_ptr().write_volatile(Mac802_15_4Table { - p_cmdrsp_buffer: MAC_802_15_4_CMD_BUFFER.as_mut_ptr().cast(), - p_notack_buffer: MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr().cast(), - evt_queue: core::ptr::null_mut(), - }); - }; - + pub async fn shci_c2_mac_802_15_4_init(&mut self) -> Result { self.write_and_get_response(ShciOpcode::Mac802_15_4Init, &[]).await } @@ -90,7 +85,7 @@ impl Sys { /// `HW_IPCC_SYS_EvtNot`, aka `IoBusCallBackUserEvt` (as detailed in Figure 65), aka /// [crate::sub::ble::hci::host::uart::UartHci::read]. #[cfg(feature = "ble")] - pub async fn shci_c2_ble_init(&self, param: ShciBleInitCmdParam) -> Result { + pub async fn shci_c2_ble_init(&mut self, param: ShciBleInitCmdParam) -> Result { self.write_and_get_response(ShciOpcode::BleInit, param.payload()).await } @@ -99,14 +94,15 @@ impl Sys { /// This method takes the place of the `HW_IPCC_SYS_EvtNot`/`SysUserEvtRx`/`APPE_SysUserEvtRx`, /// as the embassy implementation avoids the need to call C public bindings, and instead /// handles the event channels directly. - pub async fn read(&self) -> EvtBox { - Ipcc::receive(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, || unsafe { - if let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) { - Some(EvtBox::new(node_ptr.cast())) - } else { - None - } - }) - .await + pub async fn read<'b>(&mut self) -> EvtBox> { + self.ipcc_system_event_channel + .receive(|| unsafe { + if let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) { + Some(EvtBox::new(node_ptr.cast())) + } else { + None + } + }) + .await } } diff --git a/embassy-stm32-wpan/src/tables.rs b/embassy-stm32-wpan/src/tables.rs index 1dafed159..20d2c190f 100644 --- a/embassy-stm32-wpan/src/tables.rs +++ b/embassy-stm32-wpan/src/tables.rs @@ -191,93 +191,93 @@ pub struct RefTable { // --------------------- ref table --------------------- #[unsafe(link_section = "TL_REF_TABLE")] -pub static mut TL_REF_TABLE: MaybeUninit = MaybeUninit::uninit(); +pub static mut TL_REF_TABLE: MaybeUninit = MaybeUninit::zeroed(); #[unsafe(link_section = "MB_MEM1")] -pub static mut TL_DEVICE_INFO_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut TL_DEVICE_INFO_TABLE: Aligned> = Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM1")] -pub static mut TL_BLE_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut TL_BLE_TABLE: Aligned> = Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM1")] -pub static mut TL_THREAD_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut TL_THREAD_TABLE: Aligned> = Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM1")] -pub static mut TL_LLD_TESTS_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut TL_LLD_TESTS_TABLE: Aligned> = Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM1")] -pub static mut TL_BLE_LLD_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut TL_BLE_LLD_TABLE: Aligned> = Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM1")] -pub static mut TL_SYS_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut TL_SYS_TABLE: Aligned> = Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM1")] -pub static mut TL_MEM_MANAGER_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut TL_MEM_MANAGER_TABLE: Aligned> = Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM1")] -pub static mut TL_TRACES_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut TL_TRACES_TABLE: Aligned> = Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM1")] -pub static mut TL_MAC_802_15_4_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut TL_MAC_802_15_4_TABLE: Aligned> = Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM1")] -pub static mut TL_ZIGBEE_TABLE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut TL_ZIGBEE_TABLE: Aligned> = Aligned(MaybeUninit::zeroed()); // --------------------- tables --------------------- #[unsafe(link_section = "MB_MEM1")] -pub static mut FREE_BUF_QUEUE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut FREE_BUF_QUEUE: Aligned> = Aligned(MaybeUninit::zeroed()); #[allow(dead_code)] #[unsafe(link_section = "MB_MEM1")] -pub static mut TRACES_EVT_QUEUE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut TRACES_EVT_QUEUE: Aligned> = Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM2")] pub static mut CS_BUFFER: Aligned> = - Aligned(MaybeUninit::uninit()); + Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM2")] -pub static mut EVT_QUEUE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut EVT_QUEUE: Aligned> = Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM2")] -pub static mut SYSTEM_EVT_QUEUE: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut SYSTEM_EVT_QUEUE: Aligned> = Aligned(MaybeUninit::zeroed()); // --------------------- app tables --------------------- #[cfg(feature = "mac")] #[unsafe(link_section = "MB_MEM2")] -pub static mut MAC_802_15_4_CMD_BUFFER: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut MAC_802_15_4_CMD_BUFFER: Aligned> = Aligned(MaybeUninit::zeroed()); #[cfg(feature = "mac")] #[unsafe(link_section = "MB_MEM2")] pub static mut MAC_802_15_4_NOTIF_RSP_EVT_BUFFER: MaybeUninit< Aligned, -> = MaybeUninit::uninit(); +> = MaybeUninit::zeroed(); #[unsafe(link_section = "MB_MEM2")] -pub static mut EVT_POOL: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut EVT_POOL: Aligned> = Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM2")] -pub static mut SYS_CMD_BUF: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut SYS_CMD_BUF: Aligned> = Aligned(MaybeUninit::zeroed()); #[unsafe(link_section = "MB_MEM2")] pub static mut SYS_SPARE_EVT_BUF: Aligned> = - Aligned(MaybeUninit::uninit()); + Aligned(MaybeUninit::zeroed()); #[cfg(feature = "mac")] #[unsafe(link_section = "MB_MEM2")] pub static mut MAC_802_15_4_CNFINDNOT: Aligned> = - Aligned(MaybeUninit::uninit()); + Aligned(MaybeUninit::zeroed()); #[cfg(feature = "ble")] #[unsafe(link_section = "MB_MEM1")] -pub static mut BLE_CMD_BUFFER: Aligned> = Aligned(MaybeUninit::uninit()); +pub static mut BLE_CMD_BUFFER: Aligned> = Aligned(MaybeUninit::zeroed()); #[cfg(feature = "ble")] #[unsafe(link_section = "MB_MEM2")] pub static mut BLE_SPARE_EVT_BUF: Aligned> = - Aligned(MaybeUninit::uninit()); + Aligned(MaybeUninit::zeroed()); #[cfg(feature = "ble")] #[unsafe(link_section = "MB_MEM2")] // fuck these "magic" numbers from ST ---v---v pub static mut HCI_ACL_DATA_BUFFER: Aligned> = - Aligned(MaybeUninit::uninit()); + Aligned(MaybeUninit::zeroed()); diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs index e1d8b1c2a..10c4a820b 100644 --- a/embassy-stm32/src/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs @@ -1,9 +1,11 @@ //! Inter-Process Communication Controller (IPCC) use core::future::poll_fn; +use core::marker::PhantomData; use core::sync::atomic::{Ordering, compiler_fence}; use core::task::Poll; +use embassy_hal_internal::Peri; use embassy_sync::waitqueue::AtomicWaker; use crate::interrupt::typelevel::Interrupt; @@ -17,25 +19,16 @@ impl interrupt::typelevel::Handler for Receive unsafe fn on_interrupt() { let regs = IPCC::regs(); - let channels = [ - IpccChannel::Channel1, - IpccChannel::Channel2, - IpccChannel::Channel3, - IpccChannel::Channel4, - IpccChannel::Channel5, - IpccChannel::Channel6, - ]; - // Status register gives channel occupied status. For rx, use cpu1. let sr = regs.cpu(1).sr().read(); regs.cpu(0).mr().modify(|w| { - for channel in channels { - if sr.chf(channel as usize) { + for index in 0..5 { + if sr.chf(index as usize) { // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt - w.set_chom(channel as usize, true); + w.set_chom(index as usize, true); // There shouldn't be a race because the channel is masked only if the interrupt has fired - IPCC::state().rx_waker_for(channel).wake(); + IPCC::state().rx_waker_for(index).wake(); } } }) @@ -49,25 +42,16 @@ impl interrupt::typelevel::Handler for Transmi unsafe fn on_interrupt() { let regs = IPCC::regs(); - let channels = [ - IpccChannel::Channel1, - IpccChannel::Channel2, - IpccChannel::Channel3, - IpccChannel::Channel4, - IpccChannel::Channel5, - IpccChannel::Channel6, - ]; - // Status register gives channel occupied status. For tx, use cpu0. let sr = regs.cpu(0).sr().read(); regs.cpu(0).mr().modify(|w| { - for channel in channels { - if !sr.chf(channel as usize) { + for index in 0..5 { + if !sr.chf(index as usize) { // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt - w.set_chfm(channel as usize, true); + w.set_chfm(index as usize, true); // There shouldn't be a race because the channel is masked only if the interrupt has fired - IPCC::state().tx_waker_for(channel).wake(); + IPCC::state().tx_waker_for(index).wake(); } } }); @@ -82,76 +66,55 @@ pub struct Config { // reserved for future use } -/// Channel. -#[allow(missing_docs)] -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub enum IpccChannel { - Channel1 = 0, - Channel2 = 1, - Channel3 = 2, - Channel4 = 3, - Channel5 = 4, - Channel6 = 5, +/// IPCC TX Channel +pub struct IpccTxChannel<'a> { + index: u8, + _lifetime: PhantomData<&'a mut usize>, } -/// IPCC driver. -pub struct Ipcc; - -impl Ipcc { - /// Enable IPCC. - pub fn enable(_config: Config) { - rcc::enable_and_reset::(); - IPCC::set_cpu2(true); - - let regs = IPCC::regs(); - - regs.cpu(0).cr().modify(|w| { - w.set_rxoie(true); - w.set_txfie(true); - }); - - // enable interrupts - crate::interrupt::typelevel::IPCC_C1_RX::unpend(); - crate::interrupt::typelevel::IPCC_C1_TX::unpend(); +impl<'a> IpccTxChannel<'a> { + pub(crate) const fn new(index: u8) -> Self { + core::assert!(index < 6); - unsafe { crate::interrupt::typelevel::IPCC_C1_RX::enable() }; - unsafe { crate::interrupt::typelevel::IPCC_C1_TX::enable() }; + Self { + index: index, + _lifetime: PhantomData, + } } /// Send data to an IPCC channel. The closure is called to write the data when appropriate. - pub async fn send(channel: IpccChannel, f: impl FnOnce()) { + pub async fn send(&mut self, f: impl FnOnce()) { let regs = IPCC::regs(); - Self::flush(channel).await; + self.flush().await; f(); compiler_fence(Ordering::SeqCst); - trace!("ipcc: ch {}: send data", channel as u8); - regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)); + trace!("ipcc: ch {}: send data", self.index as u8); + regs.cpu(0).scr().write(|w| w.set_chs(self.index as usize, true)); } /// Wait for the tx channel to become clear - pub async fn flush(channel: IpccChannel) { + pub async fn flush(&mut self) { let regs = IPCC::regs(); // This is a race, but is nice for debugging - if regs.cpu(0).sr().read().chf(channel as usize) { - trace!("ipcc: ch {}: wait for tx free", channel as u8); + if regs.cpu(0).sr().read().chf(self.index as usize) { + trace!("ipcc: ch {}: wait for tx free", self.index as u8); } poll_fn(|cx| { - IPCC::state().tx_waker_for(channel).register(cx.waker()); + IPCC::state().tx_waker_for(self.index).register(cx.waker()); // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt - regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, false)); + regs.cpu(0).mr().modify(|w| w.set_chfm(self.index as usize, false)); compiler_fence(Ordering::SeqCst); - if !regs.cpu(0).sr().read().chf(channel as usize) { + if !regs.cpu(0).sr().read().chf(self.index as usize) { // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt - regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)); + regs.cpu(0).mr().modify(|w| w.set_chfm(self.index as usize, true)); Poll::Ready(()) } else { @@ -160,27 +123,44 @@ impl Ipcc { }) .await; } +} + +/// IPCC RX Channel +pub struct IpccRxChannel<'a> { + index: u8, + _lifetime: PhantomData<&'a mut usize>, +} + +impl<'a> IpccRxChannel<'a> { + pub(crate) const fn new(index: u8) -> Self { + core::assert!(index < 6); + + Self { + index: index, + _lifetime: PhantomData, + } + } /// Receive data from an IPCC channel. The closure is called to read the data when appropriate. - pub async fn receive(channel: IpccChannel, mut f: impl FnMut() -> Option) -> R { + pub async fn receive(&mut self, mut f: impl FnMut() -> Option) -> R { let regs = IPCC::regs(); loop { // This is a race, but is nice for debugging - if !regs.cpu(1).sr().read().chf(channel as usize) { - trace!("ipcc: ch {}: wait for rx occupied", channel as u8); + if !regs.cpu(1).sr().read().chf(self.index as usize) { + trace!("ipcc: ch {}: wait for rx occupied", self.index as u8); } poll_fn(|cx| { - IPCC::state().rx_waker_for(channel).register(cx.waker()); + IPCC::state().rx_waker_for(self.index).register(cx.waker()); // If bit is set to 1 then interrupt is disabled; we want to enable the interrupt - regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, false)); + regs.cpu(0).mr().modify(|w| w.set_chom(self.index as usize, false)); compiler_fence(Ordering::SeqCst); - if regs.cpu(1).sr().read().chf(channel as usize) { + if regs.cpu(1).sr().read().chf(self.index as usize) { // If bit is set to 1 then interrupt is disabled; we want to disable the interrupt - regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, true)); + regs.cpu(0).mr().modify(|w| w.set_chfm(self.index as usize, true)); Poll::Ready(()) } else { @@ -189,21 +169,111 @@ impl Ipcc { }) .await; - trace!("ipcc: ch {}: read data", channel as u8); + trace!("ipcc: ch {}: read data", self.index as u8); match f() { Some(ret) => return ret, None => {} } - trace!("ipcc: ch {}: clear rx", channel as u8); + trace!("ipcc: ch {}: clear rx", self.index as u8); compiler_fence(Ordering::SeqCst); // If the channel is clear and the read function returns none, fetch more data - regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)); + regs.cpu(0).scr().write(|w| w.set_chc(self.index as usize, true)); } } } +/// IPCC Channel +pub struct IpccChannel<'a> { + index: u8, + _lifetime: PhantomData<&'a mut usize>, +} + +impl<'a> IpccChannel<'a> { + pub(crate) const fn new(number: u8) -> Self { + core::assert!(number > 0 && number <= 6); + + Self { + index: number - 1, + _lifetime: PhantomData, + } + } + + /// Split into a tx and rx channel + pub const fn split(self) -> (IpccTxChannel<'a>, IpccRxChannel<'a>) { + (IpccTxChannel::new(self.index), IpccRxChannel::new(self.index)) + } +} + +/// IPCC driver. +pub struct Ipcc { + _private: (), +} + +impl Ipcc { + /// Creates a new HardwareSemaphore instance. + pub fn new<'d>( + _peripheral: Peri<'d, crate::peripherals::IPCC>, + _irq: impl interrupt::typelevel::Binding + + interrupt::typelevel::Binding + + 'd, + _config: Config, + ) -> Self { + rcc::enable_and_reset::(); + IPCC::set_cpu2(true); + + let regs = IPCC::regs(); + + regs.cpu(0).cr().modify(|w| { + w.set_rxoie(true); + w.set_txfie(true); + }); + + // enable interrupts + crate::interrupt::typelevel::IPCC_C1_RX::unpend(); + crate::interrupt::typelevel::IPCC_C1_TX::unpend(); + + unsafe { crate::interrupt::typelevel::IPCC_C1_RX::enable() }; + unsafe { crate::interrupt::typelevel::IPCC_C1_TX::enable() }; + + Self { _private: () } + } + + /// Split into a tx and rx channel + pub const fn split<'a>(self) -> [(IpccTxChannel<'a>, IpccRxChannel<'a>); 6] { + [ + IpccChannel::new(1).split(), + IpccChannel::new(2).split(), + IpccChannel::new(3).split(), + IpccChannel::new(4).split(), + IpccChannel::new(5).split(), + IpccChannel::new(6).split(), + ] + } + + /// Receive from a channel number + pub async unsafe fn receive(number: u8, f: impl FnMut() -> Option) -> R { + core::assert!(number > 0 && number <= 6); + + IpccRxChannel::new(number - 1).receive(f).await + } + + /// Send to a channel number + pub async unsafe fn send(number: u8, f: impl FnOnce()) { + core::assert!(number > 0 && number <= 6); + + IpccTxChannel::new(number - 1).send(f).await + } + + /// Send to a channel number + pub async unsafe fn flush(number: u8) { + core::assert!(number > 0 && number <= 6); + + IpccTxChannel::new(number - 1).flush().await + } +} + impl SealedInstance for crate::peripherals::IPCC { fn regs() -> crate::pac::ipcc::Ipcc { crate::pac::IPCC @@ -232,26 +302,12 @@ impl State { } } - const fn rx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { - match channel { - IpccChannel::Channel1 => &self.rx_wakers[0], - IpccChannel::Channel2 => &self.rx_wakers[1], - IpccChannel::Channel3 => &self.rx_wakers[2], - IpccChannel::Channel4 => &self.rx_wakers[3], - IpccChannel::Channel5 => &self.rx_wakers[4], - IpccChannel::Channel6 => &self.rx_wakers[5], - } + const fn rx_waker_for(&self, index: u8) -> &AtomicWaker { + &self.rx_wakers[index as usize] } - const fn tx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { - match channel { - IpccChannel::Channel1 => &self.tx_wakers[0], - IpccChannel::Channel2 => &self.tx_wakers[1], - IpccChannel::Channel3 => &self.tx_wakers[2], - IpccChannel::Channel4 => &self.tx_wakers[3], - IpccChannel::Channel5 => &self.tx_wakers[4], - IpccChannel::Channel6 => &self.tx_wakers[5], - } + const fn tx_waker_for(&self, index: u8) -> &AtomicWaker { + &self.tx_wakers[index as usize] } } diff --git a/examples/stm32wb/src/bin/eddystone_beacon.rs b/examples/stm32wb/src/bin/eddystone_beacon.rs index f309ca3a2..413b1ac8f 100644 --- a/examples/stm32wb/src/bin/eddystone_beacon.rs +++ b/examples/stm32wb/src/bin/eddystone_beacon.rs @@ -57,126 +57,112 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mut mbox = TlMbox::init(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config).await; + let mut sys = mbox.sys_subsystem; + let mut ble = mbox.ble_subsystem; - let sys_event = mbox.sys_subsystem.read().await; - info!("sys event: {}", sys_event.payload()); - - let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; + let _ = sys.shci_c2_ble_init(Default::default()).await; info!("resetting BLE..."); - mbox.ble_subsystem.reset().await; - let response = mbox.ble_subsystem.read().await.unwrap(); + ble.reset().await; + let response = ble.read().await.unwrap(); defmt::info!("{}", response); info!("config public address..."); - mbox.ble_subsystem - .write_config_data(&ConfigData::public_address(get_bd_addr()).build()) + ble.write_config_data(&ConfigData::public_address(get_bd_addr()).build()) .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); defmt::info!("{}", response); info!("config random address..."); - mbox.ble_subsystem - .write_config_data(&ConfigData::random_address(get_random_addr()).build()) + ble.write_config_data(&ConfigData::random_address(get_random_addr()).build()) .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); defmt::info!("{}", response); info!("config identity root..."); - mbox.ble_subsystem - .write_config_data(&ConfigData::identity_root(&get_irk()).build()) + ble.write_config_data(&ConfigData::identity_root(&get_irk()).build()) .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); defmt::info!("{}", response); info!("config encryption root..."); - mbox.ble_subsystem - .write_config_data(&ConfigData::encryption_root(&get_erk()).build()) + ble.write_config_data(&ConfigData::encryption_root(&get_erk()).build()) .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); defmt::info!("{}", response); info!("config tx power level..."); - mbox.ble_subsystem.set_tx_power_level(PowerLevel::ZerodBm).await; - let response = mbox.ble_subsystem.read().await.unwrap(); + ble.set_tx_power_level(PowerLevel::ZerodBm).await; + let response = ble.read().await.unwrap(); defmt::info!("{}", response); info!("GATT init..."); - mbox.ble_subsystem.init_gatt().await; - let response = mbox.ble_subsystem.read().await.unwrap(); + ble.init_gatt().await; + let response = ble.read().await.unwrap(); defmt::info!("{}", response); info!("GAP init..."); - mbox.ble_subsystem - .init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH) - .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + ble.init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH).await; + let response = ble.read().await.unwrap(); defmt::info!("{}", response); // info!("set scan response..."); - // mbox.ble_subsystem.le_set_scan_response_data(&[]).await.unwrap(); - // let response = mbox.ble_subsystem.read().await.unwrap(); + // ble.le_set_scan_response_data(&[]).await.unwrap(); + // let response = ble.read().await.unwrap(); // defmt::info!("{}", response); info!("set discoverable..."); - mbox.ble_subsystem - .set_discoverable(&DiscoverableParameters { - advertising_type: AdvertisingType::NonConnectableUndirected, - advertising_interval: Some((Duration::from_millis(250), Duration::from_millis(250))), - address_type: OwnAddressType::Public, - filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan, - local_name: None, - advertising_data: &[], - conn_interval: (None, None), - }) - .await - .unwrap(); - - let response = mbox.ble_subsystem.read().await; + ble.set_discoverable(&DiscoverableParameters { + advertising_type: AdvertisingType::NonConnectableUndirected, + advertising_interval: Some((Duration::from_millis(250), Duration::from_millis(250))), + address_type: OwnAddressType::Public, + filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan, + local_name: None, + advertising_data: &[], + conn_interval: (None, None), + }) + .await + .unwrap(); + + let response = ble.read().await; defmt::info!("{}", response); // remove some advertisement to decrease the packet size info!("delete tx power ad type..."); - mbox.ble_subsystem - .delete_ad_type(AdvertisingDataType::TxPowerLevel) - .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + ble.delete_ad_type(AdvertisingDataType::TxPowerLevel).await; + let response = ble.read().await.unwrap(); defmt::info!("{}", response); info!("delete conn interval ad type..."); - mbox.ble_subsystem - .delete_ad_type(AdvertisingDataType::PeripheralConnectionInterval) + ble.delete_ad_type(AdvertisingDataType::PeripheralConnectionInterval) .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); defmt::info!("{}", response); info!("update advertising data..."); - mbox.ble_subsystem - .update_advertising_data(&eddystone_advertising_data()) + ble.update_advertising_data(&eddystone_advertising_data()) .await .unwrap(); - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); defmt::info!("{}", response); info!("update advertising data type..."); - mbox.ble_subsystem - .update_advertising_data(&[3, AdvertisingDataType::UuidCompleteList16 as u8, 0xaa, 0xfe]) + ble.update_advertising_data(&[3, AdvertisingDataType::UuidCompleteList16 as u8, 0xaa, 0xfe]) .await .unwrap(); - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); defmt::info!("{}", response); info!("update advertising data flags..."); - mbox.ble_subsystem - .update_advertising_data(&[ - 2, - AdvertisingDataType::Flags as u8, - (0x02 | 0x04) as u8, // BLE general discoverable, without BR/EDR support - ]) - .await - .unwrap(); - let response = mbox.ble_subsystem.read().await.unwrap(); + ble.update_advertising_data(&[ + 2, + AdvertisingDataType::Flags as u8, + (0x02 | 0x04) as u8, // BLE general discoverable, without BR/EDR support + ]) + .await + .unwrap(); + let response = ble.read().await.unwrap(); defmt::info!("{}", response); cortex_m::asm::wfi(); diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs index 2ed257566..3484f1844 100644 --- a/examples/stm32wb/src/bin/gatt_server.rs +++ b/examples/stm32wb/src/bin/gatt_server.rs @@ -69,92 +69,85 @@ async fn main(spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mut mbox = TlMbox::init(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config).await; + let mut sys = mbox.sys_subsystem; + let mut ble = mbox.ble_subsystem; spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); - let sys_event = mbox.sys_subsystem.read().await; - info!("sys event: {}", sys_event.payload()); - let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; + let _ = sys.shci_c2_ble_init(Default::default()).await; info!("resetting BLE..."); - mbox.ble_subsystem.reset().await; - let response = mbox.ble_subsystem.read().await; + ble.reset().await; + let response = ble.read().await; defmt::debug!("{}", response); info!("config public address..."); - mbox.ble_subsystem - .write_config_data(&ConfigData::public_address(get_bd_addr()).build()) + ble.write_config_data(&ConfigData::public_address(get_bd_addr()).build()) .await; - let response = mbox.ble_subsystem.read().await; + let response = ble.read().await; defmt::debug!("{}", response); info!("config random address..."); - mbox.ble_subsystem - .write_config_data(&ConfigData::random_address(get_random_addr()).build()) + ble.write_config_data(&ConfigData::random_address(get_random_addr()).build()) .await; - let response = mbox.ble_subsystem.read().await; + let response = ble.read().await; defmt::debug!("{}", response); info!("config identity root..."); - mbox.ble_subsystem - .write_config_data(&ConfigData::identity_root(&get_irk()).build()) + ble.write_config_data(&ConfigData::identity_root(&get_irk()).build()) .await; - let response = mbox.ble_subsystem.read().await; + let response = ble.read().await; defmt::debug!("{}", response); info!("config encryption root..."); - mbox.ble_subsystem - .write_config_data(&ConfigData::encryption_root(&get_erk()).build()) + ble.write_config_data(&ConfigData::encryption_root(&get_erk()).build()) .await; - let response = mbox.ble_subsystem.read().await; + let response = ble.read().await; defmt::debug!("{}", response); info!("config tx power level..."); - mbox.ble_subsystem.set_tx_power_level(PowerLevel::ZerodBm).await; - let response = mbox.ble_subsystem.read().await; + ble.set_tx_power_level(PowerLevel::ZerodBm).await; + let response = ble.read().await; defmt::debug!("{}", response); info!("GATT init..."); - mbox.ble_subsystem.init_gatt().await; - let response = mbox.ble_subsystem.read().await; + ble.init_gatt().await; + let response = ble.read().await; defmt::debug!("{}", response); info!("GAP init..."); - mbox.ble_subsystem - .init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH) - .await; - let response = mbox.ble_subsystem.read().await; + ble.init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH).await; + let response = ble.read().await; defmt::debug!("{}", response); info!("set IO capabilities..."); - mbox.ble_subsystem.set_io_capability(IoCapability::DisplayConfirm).await; - let response = mbox.ble_subsystem.read().await; + ble.set_io_capability(IoCapability::DisplayConfirm).await; + let response = ble.read().await; defmt::debug!("{}", response); info!("set authentication requirements..."); - mbox.ble_subsystem - .set_authentication_requirement(&AuthenticationRequirements { - bonding_required: false, - keypress_notification_support: false, - mitm_protection_required: false, - encryption_key_size_range: (8, 16), - fixed_pin: Pin::Requested, - identity_address_type: AddressType::Public, - secure_connection_support: SecureConnectionSupport::Optional, - }) - .await - .unwrap(); - let response = mbox.ble_subsystem.read().await; + ble.set_authentication_requirement(&AuthenticationRequirements { + bonding_required: false, + keypress_notification_support: false, + mitm_protection_required: false, + encryption_key_size_range: (8, 16), + fixed_pin: Pin::Requested, + identity_address_type: AddressType::Public, + secure_connection_support: SecureConnectionSupport::Optional, + }) + .await + .unwrap(); + let response = ble.read().await; defmt::debug!("{}", response); info!("set scan response data..."); - mbox.ble_subsystem.le_set_scan_response_data(b"TXTX").await.unwrap(); - let response = mbox.ble_subsystem.read().await; + ble.le_set_scan_response_data(b"TXTX").await.unwrap(); + let response = ble.read().await; defmt::debug!("{}", response); defmt::info!("initializing services and characteristics..."); - let mut ble_context = init_gatt_services(&mut mbox.ble_subsystem).await.unwrap(); + let mut ble_context = init_gatt_services(&mut ble).await.unwrap(); defmt::info!("{}", ble_context); let discovery_params = DiscoverableParameters { @@ -168,12 +161,12 @@ async fn main(spawner: Spawner) { }; info!("set discoverable..."); - mbox.ble_subsystem.set_discoverable(&discovery_params).await.unwrap(); - let response = mbox.ble_subsystem.read().await; + ble.set_discoverable(&discovery_params).await.unwrap(); + let response = ble.read().await; defmt::debug!("{}", response); loop { - let response = mbox.ble_subsystem.read().await; + let response = ble.read().await; defmt::debug!("{}", response); if let Ok(Packet::Event(event)) = response { @@ -184,24 +177,23 @@ async fn main(spawner: Spawner) { Event::DisconnectionComplete(_) => { defmt::info!("disconnected"); ble_context.is_subscribed = false; - mbox.ble_subsystem.set_discoverable(&discovery_params).await.unwrap(); + ble.set_discoverable(&discovery_params).await.unwrap(); } Event::Vendor(vendor_event) => match vendor_event { VendorEvent::AttReadPermitRequest(read_req) => { defmt::info!("read request received {}, allowing", read_req); - mbox.ble_subsystem.allow_read(read_req.conn_handle).await + ble.allow_read(read_req.conn_handle).await } VendorEvent::AttWritePermitRequest(write_req) => { defmt::info!("write request received {}, allowing", write_req); - mbox.ble_subsystem - .write_response(&WriteResponseParameters { - conn_handle: write_req.conn_handle, - attribute_handle: write_req.attribute_handle, - status: Ok(()), - value: write_req.value(), - }) - .await - .unwrap() + ble.write_response(&WriteResponseParameters { + conn_handle: write_req.conn_handle, + attribute_handle: write_req.attribute_handle, + status: Ok(()), + value: write_req.value(), + }) + .await + .unwrap() } VendorEvent::GattAttributeModified(attribute) => { defmt::info!("{}", ble_context); @@ -224,7 +216,7 @@ async fn main(spawner: Spawner) { } #[embassy_executor::task] -async fn run_mm_queue(memory_manager: mm::MemoryManager) { +async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { memory_manager.run_queue().await; } @@ -285,7 +277,7 @@ pub struct CharHandles { pub notify: AttributeHandle, } -pub async fn init_gatt_services(ble_subsystem: &mut Ble) -> Result { +pub async fn init_gatt_services<'a>(ble_subsystem: &mut Ble<'a>) -> Result { let service_handle = gatt_add_service(ble_subsystem, Uuid::Uuid16(0x500)).await?; let read = gatt_add_char( @@ -322,7 +314,7 @@ pub async fn init_gatt_services(ble_subsystem: &mut Ble) -> Result Result { +async fn gatt_add_service<'a>(ble_subsystem: &mut Ble<'a>, uuid: Uuid) -> Result { ble_subsystem .add_service(&AddServiceParameters { uuid, @@ -348,8 +340,8 @@ async fn gatt_add_service(ble_subsystem: &mut Ble, uuid: Uuid) -> Result( + ble_subsystem: &mut Ble<'a>, service_handle: AttributeHandle, characteristic_uuid: Uuid, characteristic_properties: CharacteristicProperty, diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 18a52e162..4bab6ea9f 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -19,7 +19,7 @@ bind_interrupts!(struct Irqs{ }); #[embassy_executor::task] -async fn run_mm_queue(memory_manager: mm::MemoryManager) { +async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { memory_manager.run_queue().await; } @@ -54,74 +54,72 @@ async fn main(spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::init(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config).await; + let mut sys = mbox.sys_subsystem; 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; + let result = sys.shci_c2_mac_802_15_4_init().await; info!("initialized mac: {}", result); + let (mut mac_rx, mut mac_tx) = mbox.mac_subsystem.split(); + info!("resetting"); - mbox.mac_subsystem + mac_tx .send_command(&ResetRequest { set_default_pib: true, ..Default::default() }) .await .unwrap(); - defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); + defmt::info!("{:#x}", mac_rx.read().await.unwrap()); info!("setting extended address"); let extended_address: u64 = 0xACDE480000000001; - mbox.mac_subsystem + mac_tx .send_command(&SetRequest { pib_attribute_ptr: &extended_address as *const _ as *const u8, pib_attribute: PibId::ExtendedAddress, }) .await .unwrap(); - defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); + defmt::info!("{:#x}", mac_rx.read().await.unwrap()); info!("setting short address"); let short_address: u16 = 0x1122; - mbox.mac_subsystem + mac_tx .send_command(&SetRequest { pib_attribute_ptr: &short_address as *const _ as *const u8, pib_attribute: PibId::ShortAddress, }) .await .unwrap(); - defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); + defmt::info!("{:#x}", mac_rx.read().await.unwrap()); info!("setting association permit"); let association_permit: bool = true; - mbox.mac_subsystem + mac_tx .send_command(&SetRequest { pib_attribute_ptr: &association_permit as *const _ as *const u8, pib_attribute: PibId::AssociationPermit, }) .await .unwrap(); - defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); + defmt::info!("{:#x}", mac_rx.read().await.unwrap()); info!("setting TX power"); let transmit_power: i8 = 2; - mbox.mac_subsystem + mac_tx .send_command(&SetRequest { pib_attribute_ptr: &transmit_power as *const _ as *const u8, pib_attribute: PibId::TransmitPower, }) .await .unwrap(); - defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); + defmt::info!("{:#x}", mac_rx.read().await.unwrap()); info!("starting FFD device"); - mbox.mac_subsystem + mac_tx .send_command(&StartRequest { pan_id: PanId([0x1A, 0xAA]), channel_number: MacChannel::Channel16, @@ -133,28 +131,27 @@ async fn main(spawner: Spawner) { }) .await .unwrap(); - defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); + defmt::info!("{:#x}", mac_rx.read().await.unwrap()); info!("setting RX on when idle"); let rx_on_while_idle: bool = true; - mbox.mac_subsystem + mac_tx .send_command(&SetRequest { pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, pib_attribute: PibId::RxOnWhenIdle, }) .await .unwrap(); - defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); + defmt::info!("{:#x}", mac_rx.read().await.unwrap()); loop { - let evt = mbox.mac_subsystem.read().await; + let evt = mac_rx.read().await; if let Ok(evt) = evt { defmt::info!("parsed mac event"); defmt::info!("{:#x}", evt); match evt { - MacEvent::MlmeAssociateInd(association) => mbox - .mac_subsystem + MacEvent::MlmeAssociateInd(association) => mac_tx .send_command(&AssociateResponse { device_address: association.device_address, assoc_short_address: [0x33, 0x44], diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs index 5d946b35b..b4789e3ee 100644 --- a/examples/stm32wb/src/bin/mac_ffd_net.rs +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs @@ -27,7 +27,7 @@ bind_interrupts!(struct Irqs{ }); #[embassy_executor::task] -async fn run_mm_queue(memory_manager: mm::MemoryManager) -> ! { +async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) -> ! { memory_manager.run_queue().await } @@ -72,15 +72,10 @@ async fn main(spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::init(p.IPCC, Irqs, config); + let mut mbox = TlMbox::init(p.IPCC, Irqs, config).await; 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); diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index 883179023..dae3c5200 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -21,7 +21,7 @@ bind_interrupts!(struct Irqs{ }); #[embassy_executor::task] -async fn run_mm_queue(memory_manager: mm::MemoryManager) { +async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { memory_manager.run_queue().await; } @@ -56,41 +56,39 @@ async fn main(spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::init(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config).await; + let mut sys = mbox.sys_subsystem; 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; + let result = sys.shci_c2_mac_802_15_4_init().await; info!("initialized mac: {}", result); + let (mut mac_rx, mut mac_tx) = mbox.mac_subsystem.split(); + info!("resetting"); - mbox.mac_subsystem + mac_tx .send_command(&ResetRequest { set_default_pib: true, ..Default::default() }) .await .unwrap(); - defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); + defmt::info!("{:#x}", mac_rx.read().await.unwrap()); info!("setting extended address"); let extended_address: u64 = 0xACDE480000000002; - mbox.mac_subsystem + mac_tx .send_command(&SetRequest { pib_attribute_ptr: &extended_address as *const _ as *const u8, pib_attribute: PibId::ExtendedAddress, }) .await .unwrap(); - defmt::info!("{:#x}", mbox.mac_subsystem.read().await.unwrap()); + defmt::info!("{:#x}", mac_rx.read().await.unwrap()); info!("getting extended address"); - mbox.mac_subsystem + mac_tx .send_command(&GetRequest { pib_attribute: PibId::ExtendedAddress, ..Default::default() @@ -99,7 +97,7 @@ async fn main(spawner: Spawner) { .unwrap(); { - let evt = mbox.mac_subsystem.read().await.unwrap(); + let evt = mac_rx.read().await.unwrap(); info!("{:#x}", evt); if let MacEvent::MlmeGetCnf(evt) = evt { @@ -125,9 +123,9 @@ async fn main(spawner: Spawner) { key_index: 152, }; info!("{}", a); - mbox.mac_subsystem.send_command(&a).await.unwrap(); + mac_tx.send_command(&a).await.unwrap(); let short_addr = { - let evt = mbox.mac_subsystem.read().await.unwrap(); + let evt = mac_rx.read().await.unwrap(); info!("{:#x}", evt); if let MacEvent::MlmeAssociateCnf(conf) = evt { @@ -138,7 +136,7 @@ async fn main(spawner: Spawner) { }; info!("setting short address"); - mbox.mac_subsystem + mac_tx .send_command(&SetRequest { pib_attribute_ptr: &short_addr as *const _ as *const u8, pib_attribute: PibId::ShortAddress, @@ -146,13 +144,13 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await.unwrap(); + let evt = mac_rx.read().await.unwrap(); info!("{:#x}", evt); } info!("sending data"); let data = b"Hello from embassy!"; - mbox.mac_subsystem + mac_tx .send_command( DataRequest { src_addr_mode: AddressMode::Short, @@ -170,12 +168,12 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await.unwrap(); + let evt = mac_rx.read().await.unwrap(); info!("{:#x}", evt); } loop { - match mbox.mac_subsystem.read().await { + match mac_rx.read().await { Ok(evt) => info!("{:#x}", evt), _ => continue, }; diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs index 4e7f2304d..0902e28e8 100644 --- a/examples/stm32wb/src/bin/tl_mbox.rs +++ b/examples/stm32wb/src/bin/tl_mbox.rs @@ -46,7 +46,7 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::init(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config).await; loop { let wireless_fw_info = mbox.sys_subsystem.wireless_fw_info(); diff --git a/examples/stm32wb/src/bin/tl_mbox_ble.rs b/examples/stm32wb/src/bin/tl_mbox_ble.rs index 72a4c18e6..763dc32cd 100644 --- a/examples/stm32wb/src/bin/tl_mbox_ble.rs +++ b/examples/stm32wb/src/bin/tl_mbox_ble.rs @@ -7,6 +7,7 @@ use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; use embassy_stm32::rcc::WPAN_DEFAULT; use embassy_stm32_wpan::TlMbox; +use embassy_stm32_wpan::sub::mm; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs{ @@ -14,8 +15,13 @@ bind_interrupts!(struct Irqs{ IPCC_C1_TX => TransmitInterruptHandler; }); +#[embassy_executor::task] +async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { + memory_manager.run_queue().await; +} + #[embassy_executor::main] -async fn main(_spawner: Spawner) { +async fn main(spawner: Spawner) { /* How to make this work: @@ -45,18 +51,19 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::init(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config).await; + let mut sys = mbox.sys_subsystem; + let mut ble = mbox.ble_subsystem; - let sys_event = mbox.sys_subsystem.read().await; - info!("sys event: {}", sys_event.payload()); + spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); - let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; + let _ = sys.shci_c2_ble_init(Default::default()).await; info!("starting ble..."); - mbox.ble_subsystem.tl_write(0x0c, &[]).await; + ble.tl_write(0x0c, &[]).await; info!("waiting for ble..."); - let ble_event = mbox.ble_subsystem.tl_read().await; + let ble_event = ble.tl_read().await; info!("ble event: {}", ble_event.payload()); diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs index 16d0a1527..235a48241 100644 --- a/examples/stm32wb/src/bin/tl_mbox_mac.rs +++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs @@ -16,7 +16,7 @@ bind_interrupts!(struct Irqs{ }); #[embassy_executor::task] -async fn run_mm_queue(memory_manager: mm::MemoryManager) { +async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { memory_manager.run_queue().await; } @@ -51,16 +51,12 @@ async fn main(spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::init(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config).await; + let mut sys = mbox.sys_subsystem; 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; + let result = sys.shci_c2_mac_802_15_4_init().await; info!("initialized mac: {}", result); // diff --git a/tests/stm32/src/bin/wpan_ble.rs b/tests/stm32/src/bin/wpan_ble.rs index 0f396b848..b4c0cbf56 100644 --- a/tests/stm32/src/bin/wpan_ble.rs +++ b/tests/stm32/src/bin/wpan_ble.rs @@ -32,7 +32,7 @@ bind_interrupts!(struct Irqs{ const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7; #[embassy_executor::task] -async fn run_mm_queue(memory_manager: mm::MemoryManager) { +async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { memory_manager.run_queue().await; } @@ -45,14 +45,13 @@ async fn main(spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mut mbox = TlMbox::init(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config).await; + let mut sys = mbox.sys_subsystem; + let mut ble = mbox.ble_subsystem; spawner.spawn(run_mm_queue(mbox.mm_subsystem).unwrap()); - let sys_event = mbox.sys_subsystem.read().await; - info!("sys event: {}", sys_event.payload()); - - let fw_info = mbox.sys_subsystem.wireless_fw_info().unwrap(); + let fw_info = sys.wireless_fw_info().unwrap(); let version_major = fw_info.version_major(); let version_minor = fw_info.version_minor(); let subversion = fw_info.subversion(); @@ -65,121 +64,108 @@ async fn main(spawner: Spawner) { version_major, version_minor, subversion, sram2a_size, sram2b_size ); - let _ = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; + let _ = sys.shci_c2_ble_init(Default::default()).await; info!("resetting BLE..."); - mbox.ble_subsystem.reset().await; - let response = mbox.ble_subsystem.read().await.unwrap(); + ble.reset().await; + let response = ble.read().await.unwrap(); info!("{}", response); info!("config public address..."); - mbox.ble_subsystem - .write_config_data(&ConfigData::public_address(get_bd_addr()).build()) + ble.write_config_data(&ConfigData::public_address(get_bd_addr()).build()) .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); info!("{}", response); info!("config random address..."); - mbox.ble_subsystem - .write_config_data(&ConfigData::random_address(get_random_addr()).build()) + ble.write_config_data(&ConfigData::random_address(get_random_addr()).build()) .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); info!("{}", response); info!("config identity root..."); - mbox.ble_subsystem - .write_config_data(&ConfigData::identity_root(&get_irk()).build()) + ble.write_config_data(&ConfigData::identity_root(&get_irk()).build()) .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); info!("{}", response); info!("config encryption root..."); - mbox.ble_subsystem - .write_config_data(&ConfigData::encryption_root(&get_erk()).build()) + ble.write_config_data(&ConfigData::encryption_root(&get_erk()).build()) .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); info!("{}", response); info!("config tx power level..."); - mbox.ble_subsystem.set_tx_power_level(PowerLevel::ZerodBm).await; - let response = mbox.ble_subsystem.read().await.unwrap(); + ble.set_tx_power_level(PowerLevel::ZerodBm).await; + let response = ble.read().await.unwrap(); info!("{}", response); info!("GATT init..."); - mbox.ble_subsystem.init_gatt().await; - let response = mbox.ble_subsystem.read().await.unwrap(); + ble.init_gatt().await; + let response = ble.read().await.unwrap(); info!("{}", response); info!("GAP init..."); - mbox.ble_subsystem - .init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH) - .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + ble.init_gap(Role::PERIPHERAL, false, BLE_GAP_DEVICE_NAME_LENGTH).await; + let response = ble.read().await.unwrap(); info!("{}", response); // info!("set scan response..."); - // mbox.ble_subsystem.le_set_scan_response_data(&[]).await.unwrap(); - // let response = mbox.ble_subsystem.read().await.unwrap(); + // ble.le_set_scan_response_data(&[]).await.unwrap(); + // let response = ble.read().await.unwrap(); // info!("{}", response); info!("set discoverable..."); - mbox.ble_subsystem - .set_discoverable(&DiscoverableParameters { - advertising_type: AdvertisingType::NonConnectableUndirected, - advertising_interval: Some((Duration::from_millis(250), Duration::from_millis(250))), - address_type: OwnAddressType::Public, - filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan, - local_name: None, - advertising_data: &[], - conn_interval: (None, None), - }) - .await - .unwrap(); - - let response = mbox.ble_subsystem.read().await; + ble.set_discoverable(&DiscoverableParameters { + advertising_type: AdvertisingType::NonConnectableUndirected, + advertising_interval: Some((Duration::from_millis(250), Duration::from_millis(250))), + address_type: OwnAddressType::Public, + filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan, + local_name: None, + advertising_data: &[], + conn_interval: (None, None), + }) + .await + .unwrap(); + + let response = ble.read().await; info!("{}", response); // remove some advertisement to decrease the packet size info!("delete tx power ad type..."); - mbox.ble_subsystem - .delete_ad_type(AdvertisingDataType::TxPowerLevel) - .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + ble.delete_ad_type(AdvertisingDataType::TxPowerLevel).await; + let response = ble.read().await.unwrap(); info!("{}", response); info!("delete conn interval ad type..."); - mbox.ble_subsystem - .delete_ad_type(AdvertisingDataType::PeripheralConnectionInterval) + ble.delete_ad_type(AdvertisingDataType::PeripheralConnectionInterval) .await; - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); info!("{}", response); info!("update advertising data..."); - mbox.ble_subsystem - .update_advertising_data(&eddystone_advertising_data()) + ble.update_advertising_data(&eddystone_advertising_data()) .await .unwrap(); - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); info!("{}", response); info!("update advertising data type..."); - mbox.ble_subsystem - .update_advertising_data(&[3, AdvertisingDataType::UuidCompleteList16 as u8, 0xaa, 0xfe]) + ble.update_advertising_data(&[3, AdvertisingDataType::UuidCompleteList16 as u8, 0xaa, 0xfe]) .await .unwrap(); - let response = mbox.ble_subsystem.read().await.unwrap(); + let response = ble.read().await.unwrap(); info!("{}", response); info!("update advertising data flags..."); - mbox.ble_subsystem - .update_advertising_data(&[ - 2, - AdvertisingDataType::Flags as u8, - (0x02 | 0x04) as u8, // BLE general discoverable, without BR/EDR support - ]) - .await - .unwrap(); - let response = mbox.ble_subsystem.read().await.unwrap(); + ble.update_advertising_data(&[ + 2, + AdvertisingDataType::Flags as u8, + (0x02 | 0x04) as u8, // BLE general discoverable, without BR/EDR support + ]) + .await + .unwrap(); + let response = ble.read().await.unwrap(); info!("{}", response); info!("Test OK"); diff --git a/tests/stm32/src/bin/wpan_mac.rs b/tests/stm32/src/bin/wpan_mac.rs index f27146c44..42db39e7e 100644 --- a/tests/stm32/src/bin/wpan_mac.rs +++ b/tests/stm32/src/bin/wpan_mac.rs @@ -25,7 +25,7 @@ bind_interrupts!(struct Irqs{ }); #[embassy_executor::task] -async fn run_mm_queue(memory_manager: mm::MemoryManager) { +async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) { memory_manager.run_queue().await; } @@ -38,20 +38,17 @@ async fn main(spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::init(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config).await; + let mut sys = mbox.sys_subsystem; + let (mut mac_rx, mut mac_tx) = mbox.mac_subsystem.split(); 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; + let result = sys.shci_c2_mac_802_15_4_init().await; info!("initialized mac: {}", result); info!("resetting"); - mbox.mac_subsystem + mac_tx .send_command(&ResetRequest { set_default_pib: true, ..Default::default() @@ -59,13 +56,13 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await.unwrap(); + let evt = mac_rx.read().await.unwrap(); info!("{:#x}", evt); } info!("setting extended address"); let extended_address: u64 = 0xACDE480000000002; - mbox.mac_subsystem + mac_tx .send_command(&SetRequest { pib_attribute_ptr: &extended_address as *const _ as *const u8, pib_attribute: PibId::ExtendedAddress, @@ -73,12 +70,12 @@ async fn main(spawner: Spawner) { .await .unwrap(); { - let evt = mbox.mac_subsystem.read().await.unwrap(); + let evt = mac_rx.read().await.unwrap(); info!("{:#x}", evt); } info!("getting extended address"); - mbox.mac_subsystem + mac_tx .send_command(&GetRequest { pib_attribute: PibId::ExtendedAddress, ..Default::default() @@ -87,7 +84,7 @@ async fn main(spawner: Spawner) { .unwrap(); { - let evt = mbox.mac_subsystem.read().await.unwrap(); + let evt = mac_rx.read().await.unwrap(); info!("{:#x}", evt); if let MacEvent::MlmeGetCnf(evt) = evt { @@ -113,8 +110,8 @@ async fn main(spawner: Spawner) { key_index: 152, }; info!("{}", a); - mbox.mac_subsystem.send_command(&a).await.unwrap(); - let short_addr = if let MacEvent::MlmeAssociateCnf(conf) = mbox.mac_subsystem.read().await.unwrap() { + mac_tx.send_command(&a).await.unwrap(); + let short_addr = if let MacEvent::MlmeAssociateCnf(conf) = mac_rx.read().await.unwrap() { conf.assoc_short_address } else { defmt::panic!() -- cgit