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 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<Ble>,
}
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 _,

View File

@ -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<CriticalSectionRawMutex, ()> = 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<WirelessFwInfoTable> {
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,
}
}
}

View File

@ -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<MemoryManager>,
}
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());

View File

@ -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<Sys>,
}
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<WirelessFwInfoTable> {
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()))

View File

@ -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) => {

View File

@ -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());

View File

@ -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());