diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index a39198d0..f0bd6f48 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -1,3 +1,5 @@ +use core::marker::PhantomData; + use embassy_stm32::ipcc::Ipcc; use crate::cmd::CmdPacket; @@ -7,10 +9,12 @@ use crate::tables::BleTable; use crate::unsafe_linked_list::LinkedListNode; use crate::{channels, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE}; -pub struct Ble; +pub struct Ble { + phantom: PhantomData, +} impl Ble { - pub(super) fn enable() { + pub(crate) fn new() -> Self { unsafe { LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); @@ -21,9 +25,11 @@ impl Ble { phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(), }); } + + Self { phantom: PhantomData } } /// `HW_IPCC_BLE_EvtNot` - pub async fn read() -> EvtBox { + pub async fn 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())) @@ -35,7 +41,7 @@ impl Ble { } /// `TL_BLE_SendCmd` - pub async fn write(opcode: u16, payload: &[u8]) { + pub async fn 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); }) @@ -43,7 +49,7 @@ impl Ble { } /// `TL_BLE_SendAclData` - pub async fn acl_write(handle: u16, payload: &[u8]) { + 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 _, diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index 2f694acf..833db0df 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -6,6 +6,7 @@ pub mod fmt; use core::mem::MaybeUninit; use core::sync::atomic::{compiler_fence, Ordering}; +use ble::Ble; use cmd::CmdPacket; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_stm32::interrupt; @@ -16,9 +17,10 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; use embassy_sync::signal::Signal; use evt::{CcEvt, EvtBox}; +use mm::MemoryManager; +use sys::Sys; use tables::{ BleTable, DeviceInfoTable, Mac802_15_4Table, MemManagerTable, RefTable, SysTable, ThreadTable, TracesTable, - WirelessFwInfoTable, }; use unsafe_linked_list::LinkedListNode; @@ -142,6 +144,10 @@ static STATE: Signal = Signal::new(); pub struct TlMbox<'d> { _ipcc: PeripheralRef<'d, IPCC>, + + pub sys_subsystem: Sys, + pub mm_subsystem: MemoryManager, + pub ble_subsystem: Ble, } impl<'d> TlMbox<'d> { @@ -226,9 +232,9 @@ impl<'d> TlMbox<'d> { Ipcc::enable(config); - sys::Sys::enable(); - ble::Ble::enable(); - mm::MemoryManager::enable(); + let sys = sys::Sys::new(); + let ble = ble::Ble::new(); + let mm = mm::MemoryManager::new(); // enable interrupts interrupt::typelevel::IPCC_C1_RX::unpend(); @@ -239,18 +245,11 @@ impl<'d> TlMbox<'d> { STATE.reset(); - Self { _ipcc: ipcc } - } - - /// Returns CPU2 wireless firmware information (if present). - pub fn wireless_fw_info(&self) -> Option { - let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table }; - - // Zero version indicates that CPU2 wasn't active and didn't fill the information table - if info.version != 0 { - Some(*info) - } else { - None + Self { + _ipcc: ipcc, + sys_subsystem: sys, + ble_subsystem: ble, + mm_subsystem: mm, } } } diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs index d0551d69..21f42409 100644 --- a/embassy-stm32-wpan/src/mm.rs +++ b/embassy-stm32-wpan/src/mm.rs @@ -1,6 +1,7 @@ //! Memory manager routines use core::future::poll_fn; +use core::marker::PhantomData; use core::task::Poll; use cortex_m::interrupt; @@ -17,10 +18,12 @@ use crate::{ static MM_WAKER: AtomicWaker = AtomicWaker::new(); -pub struct MemoryManager; +pub struct MemoryManager { + phantom: PhantomData, +} impl MemoryManager { - pub fn enable() { + pub(crate) fn new() -> Self { unsafe { LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); @@ -35,10 +38,12 @@ impl MemoryManager { tracespoolsize: 0, }); } + + Self { phantom: PhantomData } } /// SAFETY: passing a pointer to something other than an event packet is UB - pub unsafe fn drop_event_packet(evt: *mut EvtPacket) { + pub(crate) unsafe fn drop_event_packet(evt: *mut EvtPacket) { interrupt::free(|_| unsafe { LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _); }); @@ -46,7 +51,7 @@ impl MemoryManager { MM_WAKER.wake(); } - pub async fn run_queue() { + pub async fn run_queue(&self) { loop { poll_fn(|cx| unsafe { MM_WAKER.register(cx.waker()); diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs index 78c357b3..a185cd4f 100644 --- a/embassy-stm32-wpan/src/sys.rs +++ b/embassy-stm32-wpan/src/sys.rs @@ -1,16 +1,20 @@ +use core::marker::PhantomData; + use crate::cmd::CmdPacket; use crate::consts::TlPacketType; use crate::evt::EvtBox; use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT}; -use crate::tables::SysTable; +use crate::tables::{SysTable, WirelessFwInfoTable}; use crate::unsafe_linked_list::LinkedListNode; -use crate::{channels, Ipcc, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; +use crate::{channels, Ipcc, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE}; -pub struct Sys; +pub struct Sys { + phantom: PhantomData, +} impl Sys { /// TL_Sys_Init - pub fn enable() { + pub(crate) fn new() -> Self { unsafe { LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); @@ -19,30 +23,33 @@ impl Sys { sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), }); } + + Self { phantom: PhantomData } } - // pub async fn shci_c2_ble_init(&mut self, param: ShciBleInitCmdParam) -> SchiCommandStatus { - // let command_event = self - // .write_and_get_response(TlPacketType::SysCmd, ShciOpcode::BleInit as u16, param.payload()) - // .await; - // - // let payload = command_event.payload[0]; - // // info!("payload: {:x}", payload); - // - // payload.try_into().unwrap() - // } + /// Returns CPU2 wireless firmware information (if present). + pub fn wireless_fw_info(&self) -> Option { + let info = unsafe { TL_DEVICE_INFO_TABLE.as_mut_ptr().read_volatile().wireless_fw_info_table }; - pub fn write(opcode: u16, payload: &[u8]) { + // Zero version indicates that CPU2 wasn't active and didn't fill the information table + if info.version != 0 { + Some(info) + } else { + None + } + } + + pub fn write(&self, opcode: u16, payload: &[u8]) { unsafe { CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode, payload); } } - pub async fn shci_c2_ble_init(param: ShciBleInitCmdParam) { + pub async fn shci_c2_ble_init(&self, param: ShciBleInitCmdParam) { debug!("sending SHCI"); Ipcc::send(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, || { - Self::write(SCHI_OPCODE_BLE_INIT, param.payload()); + self.write(SCHI_OPCODE_BLE_INIT, param.payload()); }) .await; @@ -50,7 +57,7 @@ impl Sys { } /// `HW_IPCC_SYS_EvtNot` - pub async fn read() -> EvtBox { + 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())) diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs index b010fdff..9fc4b8aa 100644 --- a/examples/stm32wb/src/bin/tl_mbox.rs +++ b/examples/stm32wb/src/bin/tl_mbox.rs @@ -48,7 +48,7 @@ async fn main(_spawner: Spawner) { let mbox = TlMbox::init(p.IPCC, Irqs, config); loop { - let wireless_fw_info = mbox.wireless_fw_info(); + let wireless_fw_info = mbox.sys_subsystem.wireless_fw_info(); match wireless_fw_info { None => info!("not yet initialized"), Some(fw_info) => { diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs index 84a4f78e..439bd01a 100644 --- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs +++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs @@ -6,8 +6,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::ble::Ble; -use embassy_stm32_wpan::sys::Sys; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -46,15 +44,18 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let _ = TlMbox::init(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config); - Sys::shci_c2_ble_init(Default::default()).await; + let sys_event = mbox.sys_subsystem.read().await; + info!("sys event: {}", sys_event.payload()); + + mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; info!("starting ble..."); - Ble::write(0x0c, &[]).await; + mbox.ble_subsystem.write(0x0c, &[]).await; info!("waiting for ble..."); - let ble_event = Ble::read().await; + let ble_event = mbox.ble_subsystem.read().await; info!("ble event: {}", ble_event.payload()); diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs index 259889e3..f6641ae3 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/tl_mbox.rs @@ -13,8 +13,6 @@ use embassy_executor::Spawner; use embassy_futures::poll_once; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; -use embassy_stm32_wpan::ble::Ble; -use embassy_stm32_wpan::sys::Sys; use embassy_stm32_wpan::{mm, TlMbox}; use embassy_time::{Duration, Timer}; @@ -24,8 +22,8 @@ bind_interrupts!(struct Irqs{ }); #[embassy_executor::task] -async fn run_mm_queue() { - mm::MemoryManager::run_queue().await; +async fn run_mm_queue(memory_manager: mm::MemoryManager) { + memory_manager.run_queue().await; } #[embassy_executor::main] @@ -33,50 +31,41 @@ async fn main(spawner: Spawner) { let p = embassy_stm32::init(config()); info!("Hello World!"); - spawner.spawn(run_mm_queue()).unwrap(); - let config = Config::default(); let mbox = TlMbox::init(p.IPCC, Irqs, config); - let ready_event = Sys::read().await; - let _ = poll_once(Sys::read()); // clear rx not + spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + + let ready_event = mbox.sys_subsystem.read().await; + let _ = poll_once(mbox.sys_subsystem.read()); // clear rx not info!("coprocessor ready {}", ready_event.payload()); // test memory manager mem::drop(ready_event); - loop { - let wireless_fw_info = mbox.wireless_fw_info(); - match wireless_fw_info { - None => {} - Some(fw_info) => { - let version_major = fw_info.version_major(); - let version_minor = fw_info.version_minor(); - let subversion = fw_info.subversion(); + let fw_info = mbox.sys_subsystem.wireless_fw_info().unwrap(); + let version_major = fw_info.version_major(); + let version_minor = fw_info.version_minor(); + let subversion = fw_info.subversion(); - let sram2a_size = fw_info.sram2a_size(); - let sram2b_size = fw_info.sram2b_size(); + let sram2a_size = fw_info.sram2a_size(); + let sram2b_size = fw_info.sram2b_size(); - info!( - "version {}.{}.{} - SRAM2a {} - SRAM2b {}", - version_major, version_minor, subversion, sram2a_size, sram2b_size - ); + info!( + "version {}.{}.{} - SRAM2a {} - SRAM2b {}", + version_major, version_minor, subversion, sram2a_size, sram2b_size + ); - break; - } - } + Timer::after(Duration::from_millis(50)).await; - Timer::after(Duration::from_millis(50)).await; - } - - Sys::shci_c2_ble_init(Default::default()).await; + mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; info!("starting ble..."); - Ble::write(0x0c, &[]).await; + mbox.ble_subsystem.write(0x0c, &[]).await; info!("waiting for ble..."); - let ble_event = Ble::read().await; + let ble_event = mbox.ble_subsystem.read().await; info!("ble event: {}", ble_event.payload());