stm32/wpan: use new ownership model

This commit is contained in:
xoviat 2023-06-17 15:37:34 -05:00
parent 6d7d617f40
commit 443550b353
7 changed files with 88 additions and 81 deletions

View File

@ -1,3 +1,5 @@
use core::marker::PhantomData;
use embassy_stm32::ipcc::Ipcc; use embassy_stm32::ipcc::Ipcc;
use crate::cmd::CmdPacket; use crate::cmd::CmdPacket;
@ -7,10 +9,12 @@ use crate::tables::BleTable;
use crate::unsafe_linked_list::LinkedListNode; use crate::unsafe_linked_list::LinkedListNode;
use crate::{channels, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE}; 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<Ble>,
}
impl Ble { impl Ble {
pub(super) fn enable() { pub(crate) fn new() -> Self {
unsafe { unsafe {
LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); 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(), phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(),
}); });
} }
Self { phantom: PhantomData }
} }
/// `HW_IPCC_BLE_EvtNot` /// `HW_IPCC_BLE_EvtNot`
pub async fn read() -> EvtBox { pub async fn read(&self) -> EvtBox {
Ipcc::receive(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, || unsafe { Ipcc::receive(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, || unsafe {
if let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) { if let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) {
Some(EvtBox::new(node_ptr.cast())) Some(EvtBox::new(node_ptr.cast()))
@ -35,7 +41,7 @@ impl Ble {
} }
/// `TL_BLE_SendCmd` /// `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 { Ipcc::send(channels::cpu1::IPCC_BLE_CMD_CHANNEL, || unsafe {
CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload); CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload);
}) })
@ -43,7 +49,7 @@ impl Ble {
} }
/// `TL_BLE_SendAclData` /// `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 { Ipcc::send(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, || unsafe {
CmdPacket::write_into( CmdPacket::write_into(
HCI_ACL_DATA_BUFFER.as_mut_ptr() as *mut _, HCI_ACL_DATA_BUFFER.as_mut_ptr() as *mut _,

View File

@ -6,6 +6,7 @@ pub mod fmt;
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, Ordering};
use ble::Ble;
use cmd::CmdPacket; use cmd::CmdPacket;
use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
use embassy_stm32::interrupt; use embassy_stm32::interrupt;
@ -16,9 +17,10 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Channel; use embassy_sync::channel::Channel;
use embassy_sync::signal::Signal; use embassy_sync::signal::Signal;
use evt::{CcEvt, EvtBox}; use evt::{CcEvt, EvtBox};
use mm::MemoryManager;
use sys::Sys;
use tables::{ use tables::{
BleTable, DeviceInfoTable, Mac802_15_4Table, MemManagerTable, RefTable, SysTable, ThreadTable, TracesTable, BleTable, DeviceInfoTable, Mac802_15_4Table, MemManagerTable, RefTable, SysTable, ThreadTable, TracesTable,
WirelessFwInfoTable,
}; };
use unsafe_linked_list::LinkedListNode; use unsafe_linked_list::LinkedListNode;
@ -142,6 +144,10 @@ static STATE: Signal<CriticalSectionRawMutex, ()> = Signal::new();
pub struct TlMbox<'d> { pub struct TlMbox<'d> {
_ipcc: PeripheralRef<'d, IPCC>, _ipcc: PeripheralRef<'d, IPCC>,
pub sys_subsystem: Sys,
pub mm_subsystem: MemoryManager,
pub ble_subsystem: Ble,
} }
impl<'d> TlMbox<'d> { impl<'d> TlMbox<'d> {
@ -226,9 +232,9 @@ impl<'d> TlMbox<'d> {
Ipcc::enable(config); Ipcc::enable(config);
sys::Sys::enable(); let sys = sys::Sys::new();
ble::Ble::enable(); let ble = ble::Ble::new();
mm::MemoryManager::enable(); let mm = mm::MemoryManager::new();
// enable interrupts // enable interrupts
interrupt::typelevel::IPCC_C1_RX::unpend(); interrupt::typelevel::IPCC_C1_RX::unpend();
@ -239,18 +245,11 @@ impl<'d> TlMbox<'d> {
STATE.reset(); STATE.reset();
Self { _ipcc: ipcc } Self {
} _ipcc: ipcc,
sys_subsystem: sys,
/// Returns CPU2 wireless firmware information (if present). ble_subsystem: ble,
pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> { mm_subsystem: mm,
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
} }
} }
} }

View File

@ -1,6 +1,7 @@
//! Memory manager routines //! Memory manager routines
use core::future::poll_fn; use core::future::poll_fn;
use core::marker::PhantomData;
use core::task::Poll; use core::task::Poll;
use cortex_m::interrupt; use cortex_m::interrupt;
@ -17,10 +18,12 @@ use crate::{
static MM_WAKER: AtomicWaker = AtomicWaker::new(); static MM_WAKER: AtomicWaker = AtomicWaker::new();
pub struct MemoryManager; pub struct MemoryManager {
phantom: PhantomData<MemoryManager>,
}
impl MemoryManager { impl MemoryManager {
pub fn enable() { pub(crate) fn new() -> Self {
unsafe { unsafe {
LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr());
LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr());
@ -35,10 +38,12 @@ impl MemoryManager {
tracespoolsize: 0, tracespoolsize: 0,
}); });
} }
Self { phantom: PhantomData }
} }
/// SAFETY: passing a pointer to something other than an event packet is UB /// 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 { interrupt::free(|_| unsafe {
LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _); LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _);
}); });
@ -46,7 +51,7 @@ impl MemoryManager {
MM_WAKER.wake(); MM_WAKER.wake();
} }
pub async fn run_queue() { pub async fn run_queue(&self) {
loop { loop {
poll_fn(|cx| unsafe { poll_fn(|cx| unsafe {
MM_WAKER.register(cx.waker()); MM_WAKER.register(cx.waker());

View File

@ -1,16 +1,20 @@
use core::marker::PhantomData;
use crate::cmd::CmdPacket; use crate::cmd::CmdPacket;
use crate::consts::TlPacketType; use crate::consts::TlPacketType;
use crate::evt::EvtBox; use crate::evt::EvtBox;
use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT}; 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::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<Sys>,
}
impl Sys { impl Sys {
/// TL_Sys_Init /// TL_Sys_Init
pub fn enable() { pub(crate) fn new() -> Self {
unsafe { unsafe {
LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr());
@ -19,30 +23,33 @@ impl Sys {
sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), sys_queue: SYSTEM_EVT_QUEUE.as_ptr(),
}); });
} }
Self { phantom: PhantomData }
} }
// pub async fn shci_c2_ble_init(&mut self, param: ShciBleInitCmdParam) -> SchiCommandStatus { /// Returns CPU2 wireless firmware information (if present).
// let command_event = self pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> {
// .write_and_get_response(TlPacketType::SysCmd, ShciOpcode::BleInit as u16, param.payload()) let info = unsafe { TL_DEVICE_INFO_TABLE.as_mut_ptr().read_volatile().wireless_fw_info_table };
// .await;
//
// let payload = command_event.payload[0];
// // info!("payload: {:x}", payload);
//
// payload.try_into().unwrap()
// }
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 { unsafe {
CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode, payload); 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"); debug!("sending SHCI");
Ipcc::send(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, || { 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; .await;
@ -50,7 +57,7 @@ impl Sys {
} }
/// `HW_IPCC_SYS_EvtNot` /// `HW_IPCC_SYS_EvtNot`
pub async fn read() -> EvtBox { pub async fn read(&self) -> EvtBox {
Ipcc::receive(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, || unsafe { Ipcc::receive(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, || unsafe {
if let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) { if let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) {
Some(EvtBox::new(node_ptr.cast())) Some(EvtBox::new(node_ptr.cast()))

View File

@ -48,7 +48,7 @@ async fn main(_spawner: Spawner) {
let mbox = TlMbox::init(p.IPCC, Irqs, config); let mbox = TlMbox::init(p.IPCC, Irqs, config);
loop { loop {
let wireless_fw_info = mbox.wireless_fw_info(); let wireless_fw_info = mbox.sys_subsystem.wireless_fw_info();
match wireless_fw_info { match wireless_fw_info {
None => info!("not yet initialized"), None => info!("not yet initialized"),
Some(fw_info) => { Some(fw_info) => {

View File

@ -6,8 +6,6 @@ use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::bind_interrupts; use embassy_stm32::bind_interrupts;
use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 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 embassy_stm32_wpan::TlMbox;
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@ -46,15 +44,18 @@ async fn main(_spawner: Spawner) {
info!("Hello World!"); info!("Hello World!");
let config = Config::default(); 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..."); info!("starting ble...");
Ble::write(0x0c, &[]).await; mbox.ble_subsystem.write(0x0c, &[]).await;
info!("waiting for ble..."); info!("waiting for ble...");
let ble_event = Ble::read().await; let ble_event = mbox.ble_subsystem.read().await;
info!("ble event: {}", ble_event.payload()); info!("ble event: {}", ble_event.payload());

View File

@ -13,8 +13,6 @@ use embassy_executor::Spawner;
use embassy_futures::poll_once; use embassy_futures::poll_once;
use embassy_stm32::bind_interrupts; use embassy_stm32::bind_interrupts;
use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 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_stm32_wpan::{mm, TlMbox};
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
@ -24,8 +22,8 @@ bind_interrupts!(struct Irqs{
}); });
#[embassy_executor::task] #[embassy_executor::task]
async fn run_mm_queue() { async fn run_mm_queue(memory_manager: mm::MemoryManager) {
mm::MemoryManager::run_queue().await; memory_manager.run_queue().await;
} }
#[embassy_executor::main] #[embassy_executor::main]
@ -33,50 +31,41 @@ async fn main(spawner: Spawner) {
let p = embassy_stm32::init(config()); let p = embassy_stm32::init(config());
info!("Hello World!"); info!("Hello World!");
spawner.spawn(run_mm_queue()).unwrap();
let config = Config::default(); let config = Config::default();
let mbox = TlMbox::init(p.IPCC, Irqs, config); let mbox = TlMbox::init(p.IPCC, Irqs, config);
let ready_event = Sys::read().await; spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap();
let _ = poll_once(Sys::read()); // clear rx not
let ready_event = mbox.sys_subsystem.read().await;
let _ = poll_once(mbox.sys_subsystem.read()); // clear rx not
info!("coprocessor ready {}", ready_event.payload()); info!("coprocessor ready {}", ready_event.payload());
// test memory manager // test memory manager
mem::drop(ready_event); mem::drop(ready_event);
loop { let fw_info = mbox.sys_subsystem.wireless_fw_info().unwrap();
let wireless_fw_info = mbox.wireless_fw_info(); let version_major = fw_info.version_major();
match wireless_fw_info { let version_minor = fw_info.version_minor();
None => {} let subversion = fw_info.subversion();
Some(fw_info) => {
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 sram2a_size = fw_info.sram2a_size();
let sram2b_size = fw_info.sram2b_size(); let sram2b_size = fw_info.sram2b_size();
info!( info!(
"version {}.{}.{} - SRAM2a {} - SRAM2b {}", "version {}.{}.{} - SRAM2a {} - SRAM2b {}",
version_major, version_minor, subversion, sram2a_size, sram2b_size version_major, version_minor, subversion, sram2a_size, sram2b_size
); );
break; Timer::after(Duration::from_millis(50)).await;
}
}
Timer::after(Duration::from_millis(50)).await; mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await;
}
Sys::shci_c2_ble_init(Default::default()).await;
info!("starting ble..."); info!("starting ble...");
Ble::write(0x0c, &[]).await; mbox.ble_subsystem.write(0x0c, &[]).await;
info!("waiting for ble..."); info!("waiting for ble...");
let ble_event = Ble::read().await; let ble_event = mbox.ble_subsystem.read().await;
info!("ble event: {}", ble_event.payload()); info!("ble event: {}", ble_event.payload());