From ce1d72c609ae1e04410e68458ec3d6c36c7dae27 Mon Sep 17 00:00:00 2001 From: goueslati Date: Thu, 8 Jun 2023 16:26:47 +0100 Subject: wip --- embassy-stm32/src/tl_mbox/ble.rs | 39 +++- embassy-stm32/src/tl_mbox/cmd.rs | 42 +++- embassy-stm32/src/tl_mbox/consts.rs | 4 +- embassy-stm32/src/tl_mbox/evt.rs | 106 ++++++--- embassy-stm32/src/tl_mbox/hci.rs | 60 +++++ embassy-stm32/src/tl_mbox/mm.rs | 58 ++--- embassy-stm32/src/tl_mbox/mod.rs | 359 ++++++++++++++++-------------- embassy-stm32/src/tl_mbox/shci.rs | 35 ++- embassy-stm32/src/tl_mbox/sys.rs | 67 +++--- examples/stm32wb/src/bin/tl_mbox_tx_rx.rs | 55 +---- 10 files changed, 482 insertions(+), 343 deletions(-) create mode 100644 embassy-stm32/src/tl_mbox/hci.rs diff --git a/embassy-stm32/src/tl_mbox/ble.rs b/embassy-stm32/src/tl_mbox/ble.rs index 062377999..45bf81ef2 100644 --- a/embassy-stm32/src/tl_mbox/ble.rs +++ b/embassy-stm32/src/tl_mbox/ble.rs @@ -1,35 +1,36 @@ use embassy_futures::block_on; -use super::cmd::CmdSerial; +use super::cmd::{CmdPacket, CmdSerial}; use super::consts::TlPacketType; use super::evt::EvtBox; +use super::ipcc::Ipcc; use super::unsafe_linked_list::LinkedListNode; use super::{ - channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE, TL_CHANNEL, + channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, HEAPLESS_EVT_QUEUE, TL_BLE_TABLE, TL_REF_TABLE, }; -use crate::tl_mbox::cmd::CmdPacket; -use crate::tl_mbox::ipcc::Ipcc; pub struct Ble; impl Ble { - pub fn enable() { + pub(super) fn new() -> Self { unsafe { LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable { pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), - pcs_buffer: CS_BUFFER.as_mut_ptr().cast(), + pcs_buffer: CS_BUFFER.as_ptr().cast(), pevt_queue: EVT_QUEUE.as_ptr().cast(), phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(), }); } Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true); + + Ble } - pub fn evt_handler() { + pub(super) fn evt_handler() { unsafe { let mut node_ptr = core::ptr::null_mut(); let node_ptr_ptr: *mut _ = &mut node_ptr; @@ -40,25 +41,41 @@ impl Ble { let event = node_ptr.cast(); let event = EvtBox::new(event); - block_on(TL_CHANNEL.send(event)); + block_on(HEAPLESS_EVT_QUEUE.send(event)); } } Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL); } + pub(super) fn acl_data_handler(&self) { + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, false); + + // TODO: ACL data ack to the user + } + pub fn send_cmd(buf: &[u8]) { unsafe { let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; - let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmd_serial; + let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmdserial; let pcmd_serial_buf: *mut u8 = pcmd_serial.cast(); core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len()); - let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; - cmd_packet.cmd_serial.ty = TlPacketType::BleCmd as u8; + let mut cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; + cmd_packet.cmdserial.ty = TlPacketType::BleCmd as u8; } Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL); } + + #[allow(dead_code)] // Not used currently but reserved + pub(super) fn send_acl_data() { + let cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; + + cmd_packet.acl_data_serial.ty = TlPacketType::AclData as u8; + + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL); + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, true); + } } diff --git a/embassy-stm32/src/tl_mbox/cmd.rs b/embassy-stm32/src/tl_mbox/cmd.rs index 3507c3231..781aa669d 100644 --- a/embassy-stm32/src/tl_mbox/cmd.rs +++ b/embassy-stm32/src/tl_mbox/cmd.rs @@ -1,7 +1,8 @@ -use super::PacketHeader; +use crate::tl_mbox::evt::{EvtPacket, EvtSerial}; +use crate::tl_mbox::{PacketHeader, TL_EVT_HEADER_SIZE}; -#[repr(C, packed)] #[derive(Copy, Clone)] +#[repr(C, packed)] pub struct Cmd { pub cmd_code: u16, pub payload_len: u8, @@ -18,22 +19,49 @@ impl Default for Cmd { } } -#[repr(C, packed)] #[derive(Copy, Clone, Default)] +#[repr(C, packed)] pub struct CmdSerial { pub ty: u8, pub cmd: Cmd, } -#[repr(C, packed)] #[derive(Copy, Clone, Default)] +#[repr(C, packed)] pub struct CmdPacket { pub header: PacketHeader, - pub cmd_serial: CmdSerial, + pub cmdserial: CmdSerial, +} + +impl CmdPacket { + /// Writes an underlying CmdPacket into the provided buffer. + /// Returns a number of bytes that were written. + /// Returns an error if event kind is unknown or if provided buffer size is not enough. + #[allow(clippy::result_unit_err)] + pub fn write(&self, buf: &mut [u8]) -> Result { + unsafe { + let cmd_ptr: *const CmdPacket = self; + let self_as_evt_ptr: *const EvtPacket = cmd_ptr.cast(); + let evt_serial: *const EvtSerial = &(*self_as_evt_ptr).evt_serial; + + let acl_data: *const AclDataPacket = cmd_ptr.cast(); + let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; + let acl_serial_buf: *const u8 = acl_serial.cast(); + + let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE; + if len > buf.len() { + return Err(()); + } + + core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len); + + Ok(len) + } + } } -#[repr(C, packed)] #[derive(Copy, Clone)] +#[repr(C, packed)] pub struct AclDataSerial { pub ty: u8, pub handle: u16, @@ -41,8 +69,8 @@ pub struct AclDataSerial { pub acl_data: [u8; 1], } -#[repr(C, packed)] #[derive(Copy, Clone)] +#[repr(C, packed)] pub struct AclDataPacket { pub header: PacketHeader, pub acl_data_serial: AclDataSerial, diff --git a/embassy-stm32/src/tl_mbox/consts.rs b/embassy-stm32/src/tl_mbox/consts.rs index e16a26cd0..caf26c06b 100644 --- a/embassy-stm32/src/tl_mbox/consts.rs +++ b/embassy-stm32/src/tl_mbox/consts.rs @@ -1,4 +1,6 @@ -#[derive(PartialEq)] +use core::convert::TryFrom; + +#[derive(Debug)] #[repr(C)] pub enum TlPacketType { BleCmd = 0x01, diff --git a/embassy-stm32/src/tl_mbox/evt.rs b/embassy-stm32/src/tl_mbox/evt.rs index 47a8b72fd..77ce7b4ca 100644 --- a/embassy-stm32/src/tl_mbox/evt.rs +++ b/embassy-stm32/src/tl_mbox/evt.rs @@ -2,11 +2,13 @@ use core::mem::MaybeUninit; use super::cmd::{AclDataPacket, AclDataSerial}; use super::consts::TlPacketType; +use super::mm::MemoryManager; use super::{PacketHeader, TL_EVT_HEADER_SIZE}; -use crate::tl_mbox::mm::MemoryManager; -/// the payload of [`Evt`] for a command status event -#[derive(Copy, Clone)] +/** + * The payload of `Evt` for a command status event + */ +#[derive(Debug, Copy, Clone)] #[repr(C, packed)] pub struct CsEvt { pub status: u8, @@ -14,16 +16,39 @@ pub struct CsEvt { pub cmd_code: u16, } -/// the payload of [`Evt`] for a command complete event -#[derive(Clone, Copy, Default)] +/** + * The payload of `Evt` for a command complete event + */ +#[derive(Debug, Copy, Clone, Default)] #[repr(C, packed)] pub struct CcEvt { pub num_cmd: u8, - pub cmd_code: u8, + pub cmd_code: u16, pub payload: [u8; 1], } -#[derive(Clone, Copy, Default)] +impl CcEvt { + pub fn write(&self, buf: &mut [u8]) { + unsafe { + let len = core::mem::size_of::(); + assert!(buf.len() >= len); + + let self_ptr: *const CcEvt = self; + let self_buf_ptr: *const u8 = self_ptr.cast(); + + core::ptr::copy(self_buf_ptr, buf.as_mut_ptr(), len); + } + } +} + +#[derive(Debug, Copy, Clone, Default)] +#[repr(C, packed)] +pub struct AsynchEvt { + sub_evt_code: u16, + payload: [u8; 1], +} + +#[derive(Debug, Copy, Clone, Default)] #[repr(C, packed)] pub struct Evt { pub evt_code: u8, @@ -31,7 +56,7 @@ pub struct Evt { pub payload: [u8; 1], } -#[derive(Clone, Copy, Default)] +#[derive(Debug, Copy, Clone, Default)] #[repr(C, packed)] pub struct EvtSerial { pub kind: u8, @@ -46,14 +71,26 @@ pub struct EvtSerial { /// Be careful that the asynchronous events reported by the CPU2 on the system channel do /// include the header and shall use `EvtPacket` format. Only the command response format on the /// system channel is different. -#[derive(Clone, Copy, Default)] +#[derive(Copy, Clone, Default)] #[repr(C, packed)] pub struct EvtPacket { pub header: PacketHeader, pub evt_serial: EvtSerial, } -/// Smart pointer to the [`EvtPacket`] that will dispose of it automatically on drop +impl EvtPacket { + pub fn kind(&self) -> u8 { + self.evt_serial.kind + } + + pub fn evt(&self) -> &Evt { + &self.evt_serial.evt + } +} + +/// smart pointer to the [`EvtPacket`] that will dispose of [`EvtPacket`] buffer automatically +/// on [`Drop`] +#[derive(Debug)] pub struct EvtBox { ptr: *mut EvtPacket, } @@ -64,7 +101,7 @@ impl EvtBox { Self { ptr } } - /// Copies the event data from inner pointer and returns and event structure + /// copies event data from inner pointer and returns an event structure pub fn evt(&self) -> EvtPacket { let mut evt = MaybeUninit::uninit(); unsafe { @@ -73,28 +110,11 @@ impl EvtBox { } } - /// Returns the size of a buffer required to hold this event - pub fn size(&self) -> Result { - unsafe { - let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; - - if evt_kind == TlPacketType::AclData { - let acl_data: *const AclDataPacket = self.ptr.cast(); - let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; - - Ok((*acl_serial).length as usize + 5) - } else { - let evt_data: *const EvtPacket = self.ptr.cast(); - let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; - - Ok((*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE) - } - } - } - - /// writes an underlying [`EvtPacket`] into the provided buffer. Returns the number of bytes that were - /// written. Returns an error if event kind is unkown or if provided buffer size is not enough - pub fn copy_into_slice(&self, buf: &mut [u8]) -> Result { + /// writes an underlying [`EvtPacket`] into the provided buffer. + /// Returns the number of bytes that were written. + /// Returns an error if event kind is unknown or if provided buffer size is not enough. + #[allow(clippy::result_unit_err)] + pub fn write(&self, buf: &mut [u8]) -> Result { unsafe { let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; @@ -127,6 +147,26 @@ impl EvtBox { } } } + + /// returns the size of a buffer required to hold this event + #[allow(clippy::result_unit_err)] + pub fn size(&self) -> Result { + unsafe { + let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; + + let evt_data: *const EvtPacket = self.ptr.cast(); + let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; + + let acl_data: *const AclDataPacket = self.ptr.cast(); + let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; + + if let TlPacketType::AclData = evt_kind { + Ok((*acl_serial).length as usize + 5) + } else { + Ok((*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE) + } + } + } } impl Drop for EvtBox { diff --git a/embassy-stm32/src/tl_mbox/hci.rs b/embassy-stm32/src/tl_mbox/hci.rs new file mode 100644 index 000000000..5bb4ba666 --- /dev/null +++ b/embassy-stm32/src/tl_mbox/hci.rs @@ -0,0 +1,60 @@ +use super::ble::Ble; +use super::consts::TlPacketType; +use super::evt::CcEvt; +use super::shci::{shci_ble_init, ShciBleInitCmdParam}; +use super::{TlMbox, STATE}; + +pub struct RadioCoprocessor<'d> { + mbox: TlMbox<'d>, + config: ShciBleInitCmdParam, + rx_buffer: [u8; 500], +} + +impl<'d> RadioCoprocessor<'d> { + pub fn new(mbox: TlMbox<'d>, config: ShciBleInitCmdParam) -> Self { + Self { + mbox, + config, + rx_buffer: [0u8; 500], + } + } + + pub fn write(&mut self, params: &[u8]) -> Result<(), ()> { + let cmd_code = params[0]; + let cmd = TlPacketType::try_from(cmd_code)?; + + match cmd { + TlPacketType::BleCmd => Ble::send_cmd(params), + _ => todo!(), + } + + Ok(()) + } + + pub async fn read(&mut self) -> &[u8] { + self.rx_buffer = [0u8; 500]; + + loop { + STATE.wait().await; + + if let Some(evt) = self.mbox.dequeue_event() { + let event = evt.evt(); + evt.write(&mut self.rx_buffer).unwrap(); + + if event.kind() == 18 { + shci_ble_init(self.config); + self.rx_buffer[0] = 0x04; // replace event code with one that is supported by HCI + } + + if let Some(cc) = self.mbox.pop_last_cc_evt() { + + + continue; + } + + let payload_len = self.rx_buffer[2]; + return &self.rx_buffer[..3 + payload_len as usize]; + } + } + } +} diff --git a/embassy-stm32/src/tl_mbox/mm.rs b/embassy-stm32/src/tl_mbox/mm.rs index e28a6aa0c..a40438499 100644 --- a/embassy-stm32/src/tl_mbox/mm.rs +++ b/embassy-stm32/src/tl_mbox/mm.rs @@ -1,56 +1,57 @@ +//! Memory manager routines + +use core::mem::MaybeUninit; + use super::evt::EvtPacket; +use super::ipcc::Ipcc; use super::unsafe_linked_list::LinkedListNode; use super::{ - channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUFF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, + channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, TL_REF_TABLE, }; -use crate::tl_mbox::ipcc::Ipcc; -pub struct MemoryManager; +pub(super) struct MemoryManager; impl MemoryManager { - pub fn enable() { + pub fn new() -> Self { unsafe { - LinkedListNode::init_head(FREE_BUFF_QUEUE.as_mut_ptr()); + LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); - TL_MEM_MANAGER_TABLE.as_mut_ptr().write_volatile(MemManagerTable { + TL_MEM_MANAGER_TABLE = MaybeUninit::new(MemManagerTable { spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), - ble_pool: EVT_POOL.as_ptr().cast(), - ble_pool_size: POOL_SIZE as u32, - pevt_free_buffer_queue: FREE_BUFF_QUEUE.as_mut_ptr(), + blepool: EVT_POOL.as_ptr().cast(), + blepoolsize: POOL_SIZE as u32, + pevt_free_buffer_queue: FREE_BUF_QUEUE.as_mut_ptr(), traces_evt_pool: core::ptr::null(), - traces_pool_size: 0, + tracespoolsize: 0, }); } - } - pub fn evt_handler() { - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false); - Self::send_free_buf(); - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + MemoryManager } pub fn evt_drop(evt: *mut EvtPacket) { unsafe { let list_node = evt.cast(); - LinkedListNode::remove_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); - } + LinkedListNode::insert_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); - let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); - // postpone event buffer freeing to IPCC interrupt handler - if channel_is_busy { - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); - } else { - Self::send_free_buf(); - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + // postpone event buffer freeing to IPCC interrupt handler + if channel_is_busy { + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); + } else { + Self::send_free_buf(); + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + } } } - fn send_free_buf() { + /// gives free event buffers back to CPU2 from local buffer queue + pub fn send_free_buf() { unsafe { let mut node_ptr = core::ptr::null_mut(); let node_ptr_ptr: *mut _ = &mut node_ptr; @@ -64,4 +65,11 @@ impl MemoryManager { } } } + + /// free buffer channel interrupt handler + pub fn free_buf_handler() { + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false); + Self::send_free_buf(); + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + } } diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32/src/tl_mbox/mod.rs index efbbf2d1d..21a954417 100644 --- a/embassy-stm32/src/tl_mbox/mod.rs +++ b/embassy-stm32/src/tl_mbox/mod.rs @@ -1,79 +1,50 @@ use core::mem::MaybeUninit; -use atomic_polyfill::{compiler_fence, Ordering}; use bit_field::BitField; use embassy_cortex_m::interrupt::Interrupt; +use embassy_futures::block_on; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::Channel; +use embassy_sync::signal::Signal; -use self::ble::Ble; use self::cmd::{AclDataPacket, CmdPacket}; -use self::evt::{CsEvt, EvtBox}; -use self::mm::MemoryManager; -use self::shci::{shci_ble_init, ShciBleInitCmdParam}; -use self::sys::Sys; +use self::evt::{CcEvt, EvtBox}; +use self::ipcc::{Config, Ipcc}; use self::unsafe_linked_list::LinkedListNode; use crate::interrupt; use crate::peripherals::IPCC; -pub use crate::tl_mbox::ipcc::Config; -use crate::tl_mbox::ipcc::Ipcc; - -mod ble; -mod channels; -mod cmd; -mod consts; -mod evt; -mod ipcc; -mod mm; -mod shci; -mod sys; -mod unsafe_linked_list; - -pub type PacketHeader = LinkedListNode; -const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::(); -const TL_EVT_HEADER_SIZE: usize = 3; -const TL_CS_EVT_SIZE: usize = core::mem::size_of::(); - -const CFG_TL_BLE_EVT_QUEUE_LENGTH: usize = 5; -const CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255; -const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE; - -const POOL_SIZE: usize = CFG_TL_BLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); - -const fn divc(x: usize, y: usize) -> usize { - (x + y - 1) / y -} - -#[repr(C, packed)] -#[derive(Copy, Clone)] -pub struct SafeBootInfoTable { - version: u32, -} - -#[repr(C, packed)] -#[derive(Copy, Clone)] -pub struct FusInfoTable { - version: u32, - memory_size: u32, - fus_info: u32, -} +pub mod ble; +pub mod channels; +pub mod cmd; +pub mod consts; +pub mod evt; +pub mod hci; +pub mod ipcc; +pub mod mm; +pub mod shci; +pub mod sys; +pub mod unsafe_linked_list; /// Interrupt handler. pub struct ReceiveInterruptHandler {} impl interrupt::Handler for ReceiveInterruptHandler { unsafe fn on_interrupt() { - // info!("ipcc rx interrupt"); + debug!("ipcc rx interrupt"); if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { + debug!("sys evt"); sys::Sys::evt_handler(); } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) { + debug!("ble evt"); ble::Ble::evt_handler(); } else { todo!() } + + STATE.signal(()); } } @@ -81,37 +52,62 @@ pub struct TransmitInterruptHandler {} impl interrupt::Handler for TransmitInterruptHandler { unsafe fn on_interrupt() { - // info!("ipcc tx interrupt"); + debug!("ipcc tx interrupt"); if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { + debug!("sys cmd rsp"); // TODO: handle this case - let _ = sys::Sys::cmd_evt_handler(); + let cc = sys::Sys::cmd_evt_handler(); + let a = unsafe { core::slice::from_raw_parts(&cc as *const _ as *const u8, core::mem::size_of::()) }; + debug!("{:#04x}", a); + + LAST_CC_EVT.signal(cc); } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) { - mm::MemoryManager::evt_handler(); + debug!("mm"); + mm::MemoryManager::free_buf_handler(); } else { todo!() } + + STATE.signal(()); } } -/// # Version -/// - 0 -> 3 = Build - 0: Untracked - 15:Released - x: Tracked version -/// - 4 -> 7 = branch - 0: Mass Market - x: ... -/// - 8 -> 15 = Subversion -/// - 16 -> 23 = Version minor -/// - 24 -> 31 = Version major -/// # Memory Size -/// - 0 -> 7 = Flash ( Number of 4k sector) -/// - 8 -> 15 = Reserved ( Shall be set to 0 - may be used as flash extension ) -/// - 16 -> 23 = SRAM2b ( Number of 1k sector) -/// - 24 -> 31 = SRAM2a ( Number of 1k sector) +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +pub struct SafeBootInfoTable { + version: u32, +} + +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +pub struct RssInfoTable { + version: u32, + memory_size: u32, + rss_info: u32, +} + +/** + * Version + * [0:3] = Build - 0: Untracked - 15:Released - x: Tracked version + * [4:7] = branch - 0: Mass Market - x: ... + * [8:15] = Subversion + * [16:23] = Version minor + * [24:31] = Version major + * + * Memory Size + * [0:7] = Flash ( Number of 4k sector) + * [8:15] = Reserved ( Shall be set to 0 - may be used as flash extension ) + * [16:23] = SRAM2b ( Number of 1k sector) + * [24:31] = SRAM2a ( Number of 1k sector) + */ +#[derive(Debug, Copy, Clone)] #[repr(C, packed)] -#[derive(Copy, Clone)] pub struct WirelessFwInfoTable { version: u32, memory_size: u32, - info_stack: u32, - reserved: u32, + thread_info: u32, + ble_info: u32, } impl WirelessFwInfoTable { @@ -122,42 +118,43 @@ impl WirelessFwInfoTable { pub fn version_minor(&self) -> u8 { let version = self.version; - (version.get_bits(16..23) & 0xff) as u8 + (version.clone().get_bits(16..23) & 0xff) as u8 } pub fn subversion(&self) -> u8 { let version = self.version; - (version.get_bits(8..15) & 0xff) as u8 + (version.clone().get_bits(8..15) & 0xff) as u8 } - /// size of FLASH, expressed in number of 4K sectors + /// Size of FLASH, expressed in number of 4K sectors. pub fn flash_size(&self) -> u8 { let memory_size = self.memory_size; - (memory_size.get_bits(0..7) & 0xff) as u8 + (memory_size.clone().get_bits(0..7) & 0xff) as u8 } - /// size for SRAM2a, expressed in number of 1K sectors + /// Size of SRAM2a, expressed in number of 1K sectors. pub fn sram2a_size(&self) -> u8 { let memory_size = self.memory_size; - (memory_size.get_bits(24..31) & 0xff) as u8 + (memory_size.clone().get_bits(24..31) & 0xff) as u8 } - /// size of SRAM2b, expressed in number of 1K sectors + /// Size of SRAM2b, expressed in number of 1K sectors. pub fn sram2b_size(&self) -> u8 { let memory_size = self.memory_size; - (memory_size.get_bits(16..23) & 0xff) as u8 + (memory_size.clone().get_bits(16..23) & 0xff) as u8 } } -#[repr(C, packed)] -#[derive(Copy, Clone)] +#[derive(Debug, Clone)] +#[repr(C, align(4))] pub struct DeviceInfoTable { pub safe_boot_info_table: SafeBootInfoTable, - pub fus_info_table: FusInfoTable, + pub rss_info_table: RssInfoTable, pub wireless_fw_info_table: WirelessFwInfoTable, } -#[repr(C, packed)] +#[derive(Debug)] +#[repr(C, align(4))] struct BleTable { pcmd_buffer: *mut CmdPacket, pcs_buffer: *const u8, @@ -165,81 +162,86 @@ struct BleTable { phci_acl_data_buffer: *mut AclDataPacket, } -#[repr(C, packed)] +#[derive(Debug)] +#[repr(C, align(4))] struct ThreadTable { - no_stack_buffer: *const u8, - cli_cmd_rsp_buffer: *const u8, - ot_cmd_rsp_buffer: *const u8, + nostack_buffer: *const u8, + clicmdrsp_buffer: *const u8, + otcmdrsp_buffer: *const u8, } -#[repr(C, packed)] -struct SysTable { - pcmd_buffer: *mut CmdPacket, - sys_queue: *const LinkedListNode, -} - -#[allow(dead_code)] // Not used currently but reserved -#[repr(C, packed)] -struct LldTestTable { - cli_cmd_rsp_buffer: *const u8, - m0_cmd_buffer: *const u8, +// TODO: use later +#[derive(Debug)] +#[repr(C, align(4))] +pub struct LldTestsTable { + clicmdrsp_buffer: *const u8, + m0cmd_buffer: *const u8, } -#[allow(dead_code)] // Not used currently but reserved -#[repr(C, packed)] -struct BleLldTable { - cmd_rsp_buffer: *const u8, - m0_cmd_buffer: *const u8, +// TODO: use later +#[derive(Debug)] +#[repr(C, align(4))] +pub struct BleLldTable { + cmdrsp_buffer: *const u8, + m0cmd_buffer: *const u8, } -#[allow(dead_code)] // Not used currently but reserved -#[repr(C, packed)] -struct ZigbeeTable { +// TODO: use later +#[derive(Debug)] +#[repr(C, align(4))] +pub struct ZigbeeTable { notif_m0_to_m4_buffer: *const u8, - appli_cmd_m4_to_m0_buffer: *const u8, + appli_cmd_m4_to_m0_bufer: *const u8, request_m0_to_m4_buffer: *const u8, } -#[repr(C, packed)] +#[derive(Debug)] +#[repr(C, align(4))] +struct SysTable { + pcmd_buffer: *mut CmdPacket, + sys_queue: *const LinkedListNode, +} + +#[derive(Debug)] +#[repr(C, align(4))] struct MemManagerTable { spare_ble_buffer: *const u8, spare_sys_buffer: *const u8, - ble_pool: *const u8, - ble_pool_size: u32, + blepool: *const u8, + blepoolsize: u32, pevt_free_buffer_queue: *mut LinkedListNode, traces_evt_pool: *const u8, - traces_pool_size: u32, + tracespoolsize: u32, } -#[repr(C, packed)] +#[derive(Debug)] +#[repr(C, align(4))] struct TracesTable { traces_queue: *const u8, } -#[repr(C, packed)] +#[derive(Debug)] +#[repr(C, align(4))] struct Mac802_15_4Table { - pcmd_rsp_buffer: *const u8, - pnotack_buffer: *const u8, + p_cmdrsp_buffer: *const u8, + p_notack_buffer: *const u8, evt_queue: *const u8, } -/// reference table. Contains pointers to all other tables -#[repr(C, packed)] -#[derive(Copy, Clone)] +/// Reference table. Contains pointers to all other tables. +#[derive(Debug, Copy, Clone)] +#[repr(C)] pub struct RefTable { - pub device_info_table: *const DeviceInfoTable, + device_info_table: *const DeviceInfoTable, ble_table: *const BleTable, thread_table: *const ThreadTable, sys_table: *const SysTable, mem_manager_table: *const MemManagerTable, traces_table: *const TracesTable, mac_802_15_4_table: *const Mac802_15_4Table, - zigbee_table: *const ZigbeeTable, - lld_tests_table: *const LldTestTable, - ble_lld_table: *const BleLldTable, } #[link_section = "TL_REF_TABLE"] @@ -254,12 +256,6 @@ static mut TL_BLE_TABLE: MaybeUninit = MaybeUninit::uninit(); #[link_section = "MB_MEM1"] static mut TL_THREAD_TABLE: MaybeUninit = MaybeUninit::uninit(); -#[link_section = "MB_MEM1"] -static mut TL_LLD_TESTS_TABLE: MaybeUninit = MaybeUninit::uninit(); - -#[link_section = "MB_MEM1"] -static mut TL_BLE_LLD_TABLE: MaybeUninit = MaybeUninit::uninit(); - #[link_section = "MB_MEM1"] static mut TL_SYS_TABLE: MaybeUninit = MaybeUninit::uninit(); @@ -272,15 +268,21 @@ static mut TL_TRACES_TABLE: MaybeUninit = MaybeUninit::uninit(); #[link_section = "MB_MEM1"] static mut TL_MAC_802_15_4_TABLE: MaybeUninit = MaybeUninit::uninit(); -#[link_section = "MB_MEM1"] -static mut TL_ZIGBEE_TABLE: MaybeUninit = MaybeUninit::uninit(); +#[link_section = "MB_MEM2"] +static mut FREE_BUF_QUEUE: MaybeUninit = MaybeUninit::uninit(); + +// Not in shared RAM +static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit = MaybeUninit::uninit(); #[allow(dead_code)] // Not used currently but reserved -#[link_section = "MB_MEM1"] -static mut FREE_BUFF_QUEUE: MaybeUninit = MaybeUninit::uninit(); +#[link_section = "MB_MEM2"] +static mut TRACES_EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); -// not in shared RAM -static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit = MaybeUninit::uninit(); +type PacketHeader = LinkedListNode; + +const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::(); +const TL_EVT_HEADER_SIZE: usize = 3; +const TL_CS_EVT_SIZE: usize = core::mem::size_of::(); #[link_section = "MB_MEM2"] static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> = @@ -293,7 +295,30 @@ static mut EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); static mut SYSTEM_EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); #[link_section = "MB_MEM2"] -static mut SYS_CMD_BUF: MaybeUninit = MaybeUninit::uninit(); +pub static mut SYS_CMD_BUF: MaybeUninit = MaybeUninit::uninit(); + +/** + * Queue length of BLE Event + * This parameter defines the number of asynchronous events that can be stored in the HCI layer before + * being reported to the application. When a command is sent to the BLE core coprocessor, the HCI layer + * is waiting for the event with the Num_HCI_Command_Packets set to 1. The receive queue shall be large + * enough to store all asynchronous events received in between. + * When CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE is set to 27, this allow to store three 255 bytes long asynchronous events + * between the HCI command and its event. + * This parameter depends on the value given to CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE. When the queue size is to small, + * the system may hang if the queue is full with asynchronous events and the HCI layer is still waiting + * for a CC/CS event, In that case, the notification TL_BLE_HCI_ToNot() is called to indicate + * to the application a HCI command did not receive its command event within 30s (Default HCI Timeout). + */ +const CFG_TLBLE_EVT_QUEUE_LENGTH: usize = 5; +const CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255; +const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE; + +const fn divc(x: usize, y: usize) -> usize { + ((x) + (y) - 1) / (y) +} + +const POOL_SIZE: usize = CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); #[link_section = "MB_MEM2"] static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit(); @@ -310,18 +335,27 @@ static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HE static mut BLE_CMD_BUFFER: MaybeUninit = MaybeUninit::uninit(); #[link_section = "MB_MEM2"] -// "magic" numbers from ST ---v---v +// fuck these "magic" numbers from ST ---v---v static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); -// TODO: get a better size, this is a placeholder -pub(crate) static TL_CHANNEL: Channel = Channel::new(); +static HEAPLESS_EVT_QUEUE: Channel = Channel::new(); + +static STATE: Signal = Signal::new(); + +/// current event that is produced during IPCC IRQ handler execution +/// on SYS channel +/// last received Command Complete event +static LAST_CC_EVT: Signal = Signal::new(); pub struct TlMbox<'d> { + sys: sys::Sys, + ble: ble::Ble, + _mm: mm::MemoryManager, + _ipcc: PeripheralRef<'d, IPCC>, } impl<'d> TlMbox<'d> { - /// initializes low-level transport between CPU1 and BLE stack on CPU2 pub fn new( ipcc: impl Peripheral

+ 'd, _irqs: impl interrupt::Binding @@ -331,25 +365,16 @@ impl<'d> TlMbox<'d> { into_ref!(ipcc); unsafe { - compiler_fence(Ordering::AcqRel); - TL_REF_TABLE.as_mut_ptr().write_volatile(RefTable { - device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(), + device_info_table: TL_DEVICE_INFO_TABLE.as_mut_ptr(), ble_table: TL_BLE_TABLE.as_ptr(), thread_table: TL_THREAD_TABLE.as_ptr(), sys_table: TL_SYS_TABLE.as_ptr(), mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), traces_table: TL_TRACES_TABLE.as_ptr(), mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), - zigbee_table: TL_ZIGBEE_TABLE.as_ptr(), - lld_tests_table: TL_LLD_TESTS_TABLE.as_ptr(), - ble_lld_table: TL_BLE_LLD_TABLE.as_ptr(), }); - // info!("TL_REF_TABLE addr: {:x}", TL_REF_TABLE.as_ptr() as usize); - - compiler_fence(Ordering::AcqRel); - TL_SYS_TABLE = MaybeUninit::zeroed(); TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed(); TL_BLE_TABLE = MaybeUninit::zeroed(); @@ -357,9 +382,6 @@ impl<'d> TlMbox<'d> { TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed(); TL_TRACES_TABLE = MaybeUninit::zeroed(); TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed(); - TL_ZIGBEE_TABLE = MaybeUninit::zeroed(); - TL_LLD_TESTS_TABLE = MaybeUninit::zeroed(); - TL_BLE_LLD_TABLE = MaybeUninit::zeroed(); EVT_POOL = MaybeUninit::zeroed(); SYS_SPARE_EVT_BUF = MaybeUninit::zeroed(); @@ -368,15 +390,13 @@ impl<'d> TlMbox<'d> { CS_BUFFER = MaybeUninit::zeroed(); BLE_CMD_BUFFER = MaybeUninit::zeroed(); HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed(); - - compiler_fence(Ordering::AcqRel); } Ipcc::enable(config); - Sys::enable(); - Ble::enable(); - MemoryManager::enable(); + let sys = sys::Sys::new(); + let ble = ble::Ble::new(); + let mm = mm::MemoryManager::new(); // enable interrupts crate::interrupt::IPCC_C1_RX::unpend(); @@ -385,13 +405,19 @@ impl<'d> TlMbox<'d> { unsafe { crate::interrupt::IPCC_C1_RX::enable() }; unsafe { crate::interrupt::IPCC_C1_TX::enable() }; - Self { _ipcc: ipcc } + Self { + sys, + ble, + _mm: mm, + _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 + // Zero version indicates that CPU2 wasn't active and didn't fill the information table if info.version != 0 { Some(*info) } else { @@ -399,19 +425,22 @@ impl<'d> TlMbox<'d> { } } - pub fn shci_ble_init(&self, param: ShciBleInitCmdParam) { - shci_ble_init(param); + /// picks single [`EvtBox`] from internal event queue. + /// + /// Internal event queu is populated in IPCC_RX_IRQ handler + pub fn dequeue_event(&mut self) -> Option { + HEAPLESS_EVT_QUEUE.try_recv().ok() } - pub fn send_ble_cmd(&self, buf: &[u8]) { - ble::Ble::send_cmd(buf); - } - - // pub fn send_sys_cmd(&self, buf: &[u8]) { - // sys::Sys::send_cmd(buf); - // } + /// retrieves last Command Complete event and removes it from mailbox + pub fn pop_last_cc_evt(&mut self) -> Option { + if LAST_CC_EVT.signaled() { + let cc = Some(block_on(LAST_CC_EVT.wait())); + LAST_CC_EVT.reset(); - pub async fn read(&self) -> EvtBox { - TL_CHANNEL.recv().await + cc + } else { + None + } } } diff --git a/embassy-stm32/src/tl_mbox/shci.rs b/embassy-stm32/src/tl_mbox/shci.rs index 6b5b2dd19..b19baa702 100644 --- a/embassy-stm32/src/tl_mbox/shci.rs +++ b/embassy-stm32/src/tl_mbox/shci.rs @@ -1,16 +1,10 @@ -//! HCI commands for system channel - use super::cmd::CmdPacket; use super::consts::TlPacketType; -use super::{channels, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE}; -use crate::tl_mbox::ipcc::Ipcc; +use super::{sys, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE}; const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66; -pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE; -#[allow(dead_code)] -const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] #[repr(C, packed)] pub struct ShciBleInitCmdParam { /// NOT USED CURRENTLY @@ -63,39 +57,44 @@ impl Default for ShciBleInitCmdParam { } } -#[derive(Clone, Copy, Default)] +#[derive(Debug, Clone, Copy, Default)] #[repr(C, packed)] pub struct ShciHeader { metadata: [u32; 3], } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] #[repr(C, packed)] pub struct ShciBleInitCmdPacket { header: ShciHeader, param: ShciBleInitCmdParam, } +pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE; +#[allow(dead_code)] // Not used currently but reserved +const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; + pub fn shci_ble_init(param: ShciBleInitCmdParam) { + debug!("shci init"); + let mut packet = ShciBleInitCmdPacket { header: ShciHeader::default(), param, }; - let packet_ptr: *mut ShciBleInitCmdPacket = &mut packet; + let packet_ptr: *mut _ = &mut packet; unsafe { let cmd_ptr: *mut CmdPacket = packet_ptr.cast(); - (*cmd_ptr).cmd_serial.cmd.cmd_code = SCHI_OPCODE_BLE_INIT; - (*cmd_ptr).cmd_serial.cmd.payload_len = core::mem::size_of::() as u8; + (*cmd_ptr).cmdserial.cmd.cmd_code = SCHI_OPCODE_BLE_INIT; + (*cmd_ptr).cmdserial.cmd.payload_len = core::mem::size_of::() as u8; - let cmd_buf = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; - core::ptr::write(cmd_buf, *cmd_ptr); + let mut p_cmd_buffer = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; + core::ptr::write(p_cmd_buffer, *cmd_ptr); - cmd_buf.cmd_serial.ty = TlPacketType::SysCmd as u8; + p_cmd_buffer.cmdserial.ty = TlPacketType::SysCmd as u8; - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); + sys::send_cmd(); } } diff --git a/embassy-stm32/src/tl_mbox/sys.rs b/embassy-stm32/src/tl_mbox/sys.rs index 9685fb920..c87aa440c 100644 --- a/embassy-stm32/src/tl_mbox/sys.rs +++ b/embassy-stm32/src/tl_mbox/sys.rs @@ -1,45 +1,27 @@ use embassy_futures::block_on; use super::cmd::{CmdPacket, CmdSerial}; -use super::consts::TlPacketType; use super::evt::{CcEvt, EvtBox, EvtSerial}; +use super::ipcc::Ipcc; use super::unsafe_linked_list::LinkedListNode; -use super::{channels, SysTable, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_CHANNEL, TL_REF_TABLE, TL_SYS_TABLE}; -use crate::tl_mbox::ipcc::Ipcc; +use super::{channels, SysTable, HEAPLESS_EVT_QUEUE, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; pub struct Sys; impl Sys { - pub fn enable() { + pub fn new() -> Self { unsafe { LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), - }); + }) } Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true); - } - - pub fn evt_handler() { - unsafe { - let mut node_ptr = core::ptr::null_mut(); - let node_ptr_ptr: *mut _ = &mut node_ptr; - - while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { - LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); - - let event = node_ptr.cast(); - let event = EvtBox::new(event); - - // TODO: not really happy about this - block_on(TL_CHANNEL.send(event)); - } - } - Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); + Sys } pub fn cmd_evt_handler() -> CcEvt { @@ -55,29 +37,40 @@ impl Sys { // 4. CcEvt type is the actual SHCI response // 5. profit unsafe { - let cmd: *const CmdPacket = (*TL_SYS_TABLE.as_ptr()).pcmd_buffer; - let cmd_serial: *const CmdSerial = &(*cmd).cmd_serial; + let pcmd: *const CmdPacket = (*TL_SYS_TABLE.as_ptr()).pcmd_buffer; + + let a = unsafe { + core::slice::from_raw_parts(&pcmd as *const _ as *const u8, core::mem::size_of::()) + }; + debug!("shci response {:#04x}", a); + + let cmd_serial: *const CmdSerial = &(*pcmd).cmdserial; let evt_serial: *const EvtSerial = cmd_serial.cast(); - let cc = (*evt_serial).evt.payload.as_ptr().cast(); + let cc: *const CcEvt = (*evt_serial).evt.payload.as_ptr().cast(); *cc } } - #[allow(dead_code)] - pub fn send_cmd(buf: &[u8]) { + pub fn evt_handler() { unsafe { - // TODO: check this - let cmd_buffer = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer; - let cmd_serial: *mut CmdSerial = &mut cmd_buffer.cmd_serial; - let cmd_serial_buf = cmd_serial.cast(); + let mut node_ptr = core::ptr::null_mut(); + let node_ptr_ptr: *mut _ = &mut node_ptr; - core::ptr::copy(buf.as_ptr(), cmd_serial_buf, buf.len()); + while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { + LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); - let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer; - cmd_packet.cmd_serial.ty = TlPacketType::SysCmd as u8; + let event = node_ptr.cast(); + let event = EvtBox::new(event); - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); + block_on(HEAPLESS_EVT_QUEUE.send(event)); + } } + + Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); } } + +pub fn send_cmd() { + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); +} diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs index 1724d946f..0525d3f37 100644 --- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs +++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs @@ -4,7 +4,9 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::tl_mbox::{Config, TlMbox}; +use embassy_stm32::tl_mbox::hci::RadioCoprocessor; +use embassy_stm32::tl_mbox::ipcc::Config; +use embassy_stm32::tl_mbox::TlMbox; use embassy_stm32::{bind_interrupts, tl_mbox}; use {defmt_rtt as _, panic_probe as _}; @@ -45,53 +47,14 @@ async fn main(_spawner: Spawner) { let config = Config::default(); let mbox = TlMbox::new(p.IPCC, Irqs, config); - info!("waiting for coprocessor to boot"); - let event_box = mbox.read().await; + let mut rc = RadioCoprocessor::new(mbox, Default::default()); + rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]).unwrap(); - let mut payload = [0u8; 6]; - event_box.copy_into_slice(&mut payload).unwrap(); + let response = rc.read().await; + info!("coprocessor ready {}", response); - let event_packet = event_box.evt(); - let kind = event_packet.evt_serial.kind; - - // means recieved SYS event, which indicates in this case that the coprocessor is ready - if kind == 0x12 { - let code = event_packet.evt_serial.evt.evt_code; - let payload_len = event_packet.evt_serial.evt.payload_len; - - info!( - "==> kind: {:#04x}, code: {:#04x}, payload_length: {}, payload: {:#04x}", - kind, - code, - payload_len, - payload[3..] - ); - } - - // initialize ble stack, does not return a response - mbox.shci_ble_init(Default::default()); - - info!("resetting BLE"); - mbox.send_ble_cmd(&[0x01, 0x03, 0x0c, 0x00, 0x00]); - - let event_box = mbox.read().await; - - let mut payload = [0u8; 7]; - event_box.copy_into_slice(&mut payload).unwrap(); - - let event_packet = event_box.evt(); - let kind = event_packet.evt_serial.kind; - - let code = event_packet.evt_serial.evt.evt_code; - let payload_len = event_packet.evt_serial.evt.payload_len; - - info!( - "==> kind: {:#04x}, code: {:#04x}, payload_length: {}, payload: {:#04x}", - kind, - code, - payload_len, - payload[3..] - ); + let response = rc.read().await; + info!("coprocessor ready {}", response); info!("Test OK"); cortex_m::asm::bkpt(); -- cgit From ca8957da435eb91242fa33eb986e80a33bbc4da0 Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 12:27:51 +0100 Subject: stm32/ipcc: move tl_mbox into `embassy-stm32-wpan` --- embassy-stm32-wpan/Cargo.toml | 23 ++ embassy-stm32-wpan/src/ble.rs | 82 +++++ embassy-stm32-wpan/src/channels.rs | 96 +++++ embassy-stm32-wpan/src/cmd.rs | 77 ++++ embassy-stm32-wpan/src/consts.rs | 55 +++ embassy-stm32-wpan/src/evt.rs | 176 ++++++++++ embassy-stm32-wpan/src/fmt.rs | 225 ++++++++++++ embassy-stm32-wpan/src/lib.rs | 266 ++++++++++++++ embassy-stm32-wpan/src/mm.rs | 75 ++++ embassy-stm32-wpan/src/rc.rs | 50 +++ embassy-stm32-wpan/src/shci.rs | 100 ++++++ embassy-stm32-wpan/src/sys.rs | 70 ++++ embassy-stm32-wpan/src/tables.rs | 175 ++++++++++ embassy-stm32-wpan/src/unsafe_linked_list.rs | 128 +++++++ embassy-stm32/src/ipcc.rs | 234 +++++++++++++ embassy-stm32/src/lib.rs | 4 +- embassy-stm32/src/tl_mbox/ble.rs | 81 ----- embassy-stm32/src/tl_mbox/channels.rs | 104 ------ embassy-stm32/src/tl_mbox/cmd.rs | 77 ---- embassy-stm32/src/tl_mbox/consts.rs | 55 --- embassy-stm32/src/tl_mbox/evt.rs | 176 ---------- embassy-stm32/src/tl_mbox/hci.rs | 60 ---- embassy-stm32/src/tl_mbox/ipcc.rs | 174 --------- embassy-stm32/src/tl_mbox/mm.rs | 75 ---- embassy-stm32/src/tl_mbox/mod.rs | 446 ------------------------ embassy-stm32/src/tl_mbox/shci.rs | 100 ------ embassy-stm32/src/tl_mbox/sys.rs | 76 ---- embassy-stm32/src/tl_mbox/unsafe_linked_list.rs | 125 ------- examples/stm32wb/src/bin/tl_mbox_tx_rx.rs | 20 +- 29 files changed, 1844 insertions(+), 1561 deletions(-) create mode 100644 embassy-stm32-wpan/Cargo.toml create mode 100644 embassy-stm32-wpan/src/ble.rs create mode 100644 embassy-stm32-wpan/src/channels.rs create mode 100644 embassy-stm32-wpan/src/cmd.rs create mode 100644 embassy-stm32-wpan/src/consts.rs create mode 100644 embassy-stm32-wpan/src/evt.rs create mode 100644 embassy-stm32-wpan/src/fmt.rs create mode 100644 embassy-stm32-wpan/src/lib.rs create mode 100644 embassy-stm32-wpan/src/mm.rs create mode 100644 embassy-stm32-wpan/src/rc.rs create mode 100644 embassy-stm32-wpan/src/shci.rs create mode 100644 embassy-stm32-wpan/src/sys.rs create mode 100644 embassy-stm32-wpan/src/tables.rs create mode 100644 embassy-stm32-wpan/src/unsafe_linked_list.rs create mode 100644 embassy-stm32/src/ipcc.rs delete mode 100644 embassy-stm32/src/tl_mbox/ble.rs delete mode 100644 embassy-stm32/src/tl_mbox/channels.rs delete mode 100644 embassy-stm32/src/tl_mbox/cmd.rs delete mode 100644 embassy-stm32/src/tl_mbox/consts.rs delete mode 100644 embassy-stm32/src/tl_mbox/evt.rs delete mode 100644 embassy-stm32/src/tl_mbox/hci.rs delete mode 100644 embassy-stm32/src/tl_mbox/ipcc.rs delete mode 100644 embassy-stm32/src/tl_mbox/mm.rs delete mode 100644 embassy-stm32/src/tl_mbox/mod.rs delete mode 100644 embassy-stm32/src/tl_mbox/shci.rs delete mode 100644 embassy-stm32/src/tl_mbox/sys.rs delete mode 100644 embassy-stm32/src/tl_mbox/unsafe_linked_list.rs diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml new file mode 100644 index 000000000..a6673d472 --- /dev/null +++ b/embassy-stm32-wpan/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "embassy-stm32-wpan" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" + +[dependencies] +embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", features = ["stm32wb55rg"] } +embassy-sync = { version = "0.2.0", path = "../embassy-sync" } +embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } +embassy-futures = { version = "0.1.0", path = "../embassy-futures" } +embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]} +embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } +embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } + +defmt = { version = "0.3", optional = true } +cortex-m = "0.7.6" +heapless = "0.7.16" + +bit_field = "0.10.2" + +[features] +defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs new file mode 100644 index 000000000..4546bde07 --- /dev/null +++ b/embassy-stm32-wpan/src/ble.rs @@ -0,0 +1,82 @@ +use core::mem::MaybeUninit; + +use embassy_stm32::ipcc::Ipcc; + +use crate::cmd::{CmdPacket, CmdSerial}; +use crate::consts::TlPacketType; +use crate::evt::EvtBox; +use crate::tables::BleTable; +use crate::unsafe_linked_list::LinkedListNode; +use crate::{ + channels, BLE_CMD_BUFFER, CS_BUFFER, EVT_CHANNEL, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE, TL_REF_TABLE, +}; + +pub struct Ble; + +impl Ble { + pub(super) fn enable() { + unsafe { + LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); + + TL_BLE_TABLE = MaybeUninit::new(BleTable { + pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), + pcs_buffer: CS_BUFFER.as_ptr().cast(), + pevt_queue: EVT_QUEUE.as_ptr().cast(), + phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(), + }); + } + + Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true); + } + + pub(super) fn evt_handler() { + unsafe { + let mut node_ptr = core::ptr::null_mut(); + let node_ptr_ptr: *mut _ = &mut node_ptr; + + while !LinkedListNode::is_empty(EVT_QUEUE.as_mut_ptr()) { + LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); + + let event = node_ptr.cast(); + let event = EvtBox::new(event); + + EVT_CHANNEL.try_send(event).unwrap(); + } + } + + Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL); + } + + pub(super) fn acl_data_handler() { + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, false); + + // TODO: ACL data ack to the user + } + + pub fn ble_send_cmd(buf: &[u8]) { + debug!("writing ble cmd"); + + unsafe { + let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; + let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmdserial; + let pcmd_serial_buf: *mut u8 = pcmd_serial.cast(); + + core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len()); + + let mut cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; + cmd_packet.cmdserial.ty = TlPacketType::BleCmd as u8; + } + + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL); + } + + #[allow(dead_code)] // Not used currently but reserved + pub(super) fn ble_send_acl_data() { + let mut cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; + + cmd_packet.acl_data_serial.ty = TlPacketType::AclData as u8; + + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL); + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, true); + } +} diff --git a/embassy-stm32-wpan/src/channels.rs b/embassy-stm32-wpan/src/channels.rs new file mode 100644 index 000000000..9a2be1cfa --- /dev/null +++ b/embassy-stm32-wpan/src/channels.rs @@ -0,0 +1,96 @@ +//! CPU1 CPU2 +//! | (SYSTEM) | +//! |----HW_IPCC_SYSTEM_CMD_RSP_CHANNEL-------------->| +//! | | +//! |<---HW_IPCC_SYSTEM_EVENT_CHANNEL-----------------| +//! | | +//! | (ZIGBEE) | +//! |----HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL------------>| +//! | | +//! |----HW_IPCC_ZIGBEE_CMD_CLI_CHANNEL-------------->| +//! | | +//! |<---HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL-------| +//! | | +//! |<---HW_IPCC_ZIGBEE_CLI_NOTIF_ACK_CHANNEL---------| +//! | | +//! | (THREAD) | +//! |----HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL----------->| +//! | | +//! |----HW_IPCC_THREAD_CLI_CMD_CHANNEL-------------->| +//! | | +//! |<---HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL------| +//! | | +//! |<---HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL--| +//! | | +//! | (BLE) | +//! |----HW_IPCC_BLE_CMD_CHANNEL--------------------->| +//! | | +//! |----HW_IPCC_HCI_ACL_DATA_CHANNEL---------------->| +//! | | +//! |<---HW_IPCC_BLE_EVENT_CHANNEL--------------------| +//! | | +//! | (BLE LLD) | +//! |----HW_IPCC_BLE_LLD_CMD_CHANNEL----------------->| +//! | | +//! |<---HW_IPCC_BLE_LLD_RSP_CHANNEL------------------| +//! | | +//! |<---HW_IPCC_BLE_LLD_M0_CMD_CHANNEL---------------| +//! | | +//! | (MAC) | +//! |----HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL-------->| +//! | | +//! |<---HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL| +//! | | +//! | (BUFFER) | +//! |----HW_IPCC_MM_RELEASE_BUFFER_CHANNE------------>| +//! | | +//! | (TRACE) | +//! |<----HW_IPCC_TRACES_CHANNEL----------------------| +//! | | +//! + +pub mod cpu1 { + use embassy_stm32::ipcc::IpccChannel; + + pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1; + pub const IPCC_SYSTEM_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel2; + pub const IPCC_THREAD_OT_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; + #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_ZIGBEE_CMD_APPLI_CHANNEL: IpccChannel = IpccChannel::Channel3; + #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_MAC_802_15_4_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; + #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_MM_RELEASE_BUFFER_CHANNEL: IpccChannel = IpccChannel::Channel4; + pub const IPCC_THREAD_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; + #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_LLDTESTS_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; + #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_BLE_LLD_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; + pub const IPCC_HCI_ACL_DATA_CHANNEL: IpccChannel = IpccChannel::Channel6; +} + +pub mod cpu2 { + use embassy_stm32::ipcc::IpccChannel; + + pub const IPCC_BLE_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel1; + pub const IPCC_SYSTEM_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel2; + pub const IPCC_THREAD_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3; + #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3; + #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3; + #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_LDDTESTS_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; + #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_BLE_LLDÇM0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; + pub const IPCC_TRACES_CHANNEL: IpccChannel = IpccChannel::Channel4; + pub const IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel5; + #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_LLDTESTS_CLI_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5; + #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_BLE_LLD_CLI_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5; + #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_BLE_LLD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5; + #[allow(dead_code)] // Not used currently but reserved + pub const IPCC_ZIGBEE_M0_REQUEST_CHANNEL: IpccChannel = IpccChannel::Channel5; +} diff --git a/embassy-stm32-wpan/src/cmd.rs b/embassy-stm32-wpan/src/cmd.rs new file mode 100644 index 000000000..1f7dae7f7 --- /dev/null +++ b/embassy-stm32-wpan/src/cmd.rs @@ -0,0 +1,77 @@ +use crate::evt::{EvtPacket, EvtSerial}; +use crate::{PacketHeader, TL_EVT_HEADER_SIZE}; + +#[derive(Copy, Clone)] +#[repr(C, packed)] +pub struct Cmd { + pub cmd_code: u16, + pub payload_len: u8, + pub payload: [u8; 255], +} + +impl Default for Cmd { + fn default() -> Self { + Self { + cmd_code: 0, + payload_len: 0, + payload: [0u8; 255], + } + } +} + +#[derive(Copy, Clone, Default)] +#[repr(C, packed)] +pub struct CmdSerial { + pub ty: u8, + pub cmd: Cmd, +} + +#[derive(Copy, Clone, Default)] +#[repr(C, packed)] +pub struct CmdPacket { + pub header: PacketHeader, + pub cmdserial: CmdSerial, +} + +impl CmdPacket { + /// Writes an underlying CmdPacket into the provided buffer. + /// Returns a number of bytes that were written. + /// Returns an error if event kind is unknown or if provided buffer size is not enough. + #[allow(clippy::result_unit_err)] + pub fn write(&self, buf: &mut [u8]) -> Result { + unsafe { + let cmd_ptr: *const CmdPacket = self; + let self_as_evt_ptr: *const EvtPacket = cmd_ptr.cast(); + let evt_serial: *const EvtSerial = &(*self_as_evt_ptr).evt_serial; + + let acl_data: *const AclDataPacket = cmd_ptr.cast(); + let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; + let acl_serial_buf: *const u8 = acl_serial.cast(); + + let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE; + if len > buf.len() { + return Err(()); + } + + core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len); + + Ok(len) + } + } +} + +#[derive(Copy, Clone)] +#[repr(C, packed)] +pub struct AclDataSerial { + pub ty: u8, + pub handle: u16, + pub length: u16, + pub acl_data: [u8; 1], +} + +#[derive(Copy, Clone)] +#[repr(C, packed)] +pub struct AclDataPacket { + pub header: PacketHeader, + pub acl_data_serial: AclDataSerial, +} diff --git a/embassy-stm32-wpan/src/consts.rs b/embassy-stm32-wpan/src/consts.rs new file mode 100644 index 000000000..caf26c06b --- /dev/null +++ b/embassy-stm32-wpan/src/consts.rs @@ -0,0 +1,55 @@ +use core::convert::TryFrom; + +#[derive(Debug)] +#[repr(C)] +pub enum TlPacketType { + BleCmd = 0x01, + AclData = 0x02, + BleEvt = 0x04, + + OtCmd = 0x08, + OtRsp = 0x09, + CliCmd = 0x0A, + OtNot = 0x0C, + OtAck = 0x0D, + CliNot = 0x0E, + CliAck = 0x0F, + + SysCmd = 0x10, + SysRsp = 0x11, + SysEvt = 0x12, + + LocCmd = 0x20, + LocRsp = 0x21, + + TracesApp = 0x40, + TracesWl = 0x41, +} + +impl TryFrom for TlPacketType { + type Error = (); + + fn try_from(value: u8) -> Result { + match value { + 0x01 => Ok(TlPacketType::BleCmd), + 0x02 => Ok(TlPacketType::AclData), + 0x04 => Ok(TlPacketType::BleEvt), + 0x08 => Ok(TlPacketType::OtCmd), + 0x09 => Ok(TlPacketType::OtRsp), + 0x0A => Ok(TlPacketType::CliCmd), + 0x0C => Ok(TlPacketType::OtNot), + 0x0D => Ok(TlPacketType::OtAck), + 0x0E => Ok(TlPacketType::CliNot), + 0x0F => Ok(TlPacketType::CliAck), + 0x10 => Ok(TlPacketType::SysCmd), + 0x11 => Ok(TlPacketType::SysRsp), + 0x12 => Ok(TlPacketType::SysEvt), + 0x20 => Ok(TlPacketType::LocCmd), + 0x21 => Ok(TlPacketType::LocRsp), + 0x40 => Ok(TlPacketType::TracesApp), + 0x41 => Ok(TlPacketType::TracesWl), + + _ => Err(()), + } + } +} diff --git a/embassy-stm32-wpan/src/evt.rs b/embassy-stm32-wpan/src/evt.rs new file mode 100644 index 000000000..b53fe506e --- /dev/null +++ b/embassy-stm32-wpan/src/evt.rs @@ -0,0 +1,176 @@ +use core::mem::MaybeUninit; + +use super::cmd::{AclDataPacket, AclDataSerial}; +use super::consts::TlPacketType; +use super::{PacketHeader, TL_EVT_HEADER_SIZE}; +use crate::mm; + +/** + * The payload of `Evt` for a command status event + */ +#[derive(Copy, Clone)] +#[repr(C, packed)] +pub struct CsEvt { + pub status: u8, + pub num_cmd: u8, + pub cmd_code: u16, +} + +/** + * The payload of `Evt` for a command complete event + */ +#[derive(Copy, Clone, Default)] +#[repr(C, packed)] +pub struct CcEvt { + pub num_cmd: u8, + pub cmd_code: u16, + pub payload: [u8; 1], +} + +impl CcEvt { + pub fn write(&self, buf: &mut [u8]) { + unsafe { + let len = core::mem::size_of::(); + assert!(buf.len() >= len); + + let self_ptr: *const CcEvt = self; + let self_buf_ptr: *const u8 = self_ptr.cast(); + + core::ptr::copy(self_buf_ptr, buf.as_mut_ptr(), len); + } + } +} + +#[derive(Copy, Clone, Default)] +#[repr(C, packed)] +pub struct AsynchEvt { + sub_evt_code: u16, + payload: [u8; 1], +} + +#[derive(Copy, Clone, Default)] +#[repr(C, packed)] +pub struct Evt { + pub evt_code: u8, + pub payload_len: u8, + pub payload: [u8; 1], +} + +#[derive(Copy, Clone, Default)] +#[repr(C, packed)] +pub struct EvtSerial { + pub kind: u8, + pub evt: Evt, +} + +/// This format shall be used for all events (asynchronous and command response) reported +/// by the CPU2 except for the command response of a system command where the header is not there +/// and the format to be used shall be `EvtSerial`. +/// +/// ### Note: +/// Be careful that the asynchronous events reported by the CPU2 on the system channel do +/// include the header and shall use `EvtPacket` format. Only the command response format on the +/// system channel is different. +#[derive(Copy, Clone, Default)] +#[repr(C, packed)] +pub struct EvtPacket { + pub header: PacketHeader, + pub evt_serial: EvtSerial, +} + +impl EvtPacket { + pub fn kind(&self) -> u8 { + self.evt_serial.kind + } + + pub fn evt(&self) -> &Evt { + &self.evt_serial.evt + } +} + +/// smart pointer to the [`EvtPacket`] that will dispose of [`EvtPacket`] buffer automatically +/// on [`Drop`] +#[derive(Debug)] +pub struct EvtBox { + ptr: *mut EvtPacket, +} + +unsafe impl Send for EvtBox {} +impl EvtBox { + pub(super) fn new(ptr: *mut EvtPacket) -> Self { + Self { ptr } + } + + /// copies event data from inner pointer and returns an event structure + pub fn evt(&self) -> EvtPacket { + let mut evt = MaybeUninit::uninit(); + unsafe { + self.ptr.copy_to(evt.as_mut_ptr(), 1); + evt.assume_init() + } + } + + /// writes an underlying [`EvtPacket`] into the provided buffer. + /// Returns the number of bytes that were written. + /// Returns an error if event kind is unknown or if provided buffer size is not enough. + #[allow(clippy::result_unit_err)] + pub fn write(&self, buf: &mut [u8]) -> Result { + unsafe { + let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; + + let evt_data: *const EvtPacket = self.ptr.cast(); + let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; + let evt_serial_buf: *const u8 = evt_serial.cast(); + + let acl_data: *const AclDataPacket = self.ptr.cast(); + let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; + let acl_serial_buf: *const u8 = acl_serial.cast(); + + if let TlPacketType::AclData = evt_kind { + let len = (*acl_serial).length as usize + 5; + if len > buf.len() { + return Err(()); + } + + core::ptr::copy(evt_serial_buf, buf.as_mut_ptr(), len); + + Ok(len) + } else { + let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE; + if len > buf.len() { + return Err(()); + } + + core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len); + + Ok(len) + } + } + } + + /// returns the size of a buffer required to hold this event + #[allow(clippy::result_unit_err)] + pub fn size(&self) -> Result { + unsafe { + let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; + + let evt_data: *const EvtPacket = self.ptr.cast(); + let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; + + let acl_data: *const AclDataPacket = self.ptr.cast(); + let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; + + if let TlPacketType::AclData = evt_kind { + Ok((*acl_serial).length as usize + 5) + } else { + Ok((*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE) + } + } + } +} + +impl Drop for EvtBox { + fn drop(&mut self) { + mm::MemoryManager::evt_drop(self.ptr); + } +} diff --git a/embassy-stm32-wpan/src/fmt.rs b/embassy-stm32-wpan/src/fmt.rs new file mode 100644 index 000000000..066970813 --- /dev/null +++ b/embassy-stm32-wpan/src/fmt.rs @@ -0,0 +1,225 @@ +#![macro_use] +#![allow(unused_macros)] + +#[cfg(all(feature = "defmt", feature = "log"))] +compile_error!("You may not enable both `defmt` and `log` features."); + +macro_rules! assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert!($($x)*); + } + }; +} + +macro_rules! assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_eq!($($x)*); + } + }; +} + +macro_rules! assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::assert_ne!($($x)*); + } + }; +} + +macro_rules! debug_assert { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert!($($x)*); + } + }; +} + +macro_rules! debug_assert_eq { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_eq!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_eq!($($x)*); + } + }; +} + +macro_rules! debug_assert_ne { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::debug_assert_ne!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::debug_assert_ne!($($x)*); + } + }; +} + +macro_rules! todo { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::todo!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::todo!($($x)*); + } + }; +} + +macro_rules! unreachable { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::unreachable!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::unreachable!($($x)*); + } + }; +} + +macro_rules! panic { + ($($x:tt)*) => { + { + #[cfg(not(feature = "defmt"))] + ::core::panic!($($x)*); + #[cfg(feature = "defmt")] + ::defmt::panic!($($x)*); + } + }; +} + +macro_rules! trace { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::trace!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::trace!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! debug { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::debug!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::debug!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! info { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::info!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::info!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! warn { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::warn!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::warn!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +macro_rules! error { + ($s:literal $(, $x:expr)* $(,)?) => { + { + #[cfg(feature = "log")] + ::log::error!($s $(, $x)*); + #[cfg(feature = "defmt")] + ::defmt::error!($s $(, $x)*); + #[cfg(not(any(feature = "log", feature="defmt")))] + let _ = ($( & $x ),*); + } + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unwrap { + ($($x:tt)*) => { + ::defmt::unwrap!($($x)*) + }; +} + +#[cfg(not(feature = "defmt"))] +macro_rules! unwrap { + ($arg:expr) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); + } + } + }; + ($arg:expr, $($msg:expr),+ $(,)? ) => { + match $crate::fmt::Try::into_result($arg) { + ::core::result::Result::Ok(t) => t, + ::core::result::Result::Err(e) => { + ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); + } + } + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub struct NoneError; + +pub trait Try { + type Ok; + type Error; + fn into_result(self) -> Result; +} + +impl Try for Option { + type Ok = T; + type Error = NoneError; + + #[inline] + fn into_result(self) -> Result { + self.ok_or(NoneError) + } +} + +impl Try for Result { + type Ok = T; + type Error = E; + + #[inline] + fn into_result(self) -> Self { + self + } +} diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs new file mode 100644 index 000000000..b3206428e --- /dev/null +++ b/embassy-stm32-wpan/src/lib.rs @@ -0,0 +1,266 @@ +#![no_std] + +// This must go FIRST so that all the other modules see its macros. +pub mod fmt; + +use core::mem::MaybeUninit; + +use cmd::CmdPacket; +use embassy_cortex_m::interrupt::Interrupt; +use embassy_futures::block_on; +use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; +use embassy_stm32::interrupt; +use embassy_stm32::ipcc::{Config, Ipcc}; +use embassy_stm32::peripherals::IPCC; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::channel::Channel; +use embassy_sync::signal::Signal; +use evt::{CcEvt, EvtBox}; +use tables::{ + BleTable, DeviceInfoTable, Mac802_15_4Table, MemManagerTable, RefTable, SysTable, ThreadTable, TracesTable, + WirelessFwInfoTable, +}; +use unsafe_linked_list::LinkedListNode; + +pub mod ble; +pub mod channels; +pub mod cmd; +pub mod consts; +pub mod evt; +pub mod mm; +pub mod rc; +pub mod shci; +pub mod sys; +pub mod tables; +pub mod unsafe_linked_list; + +/// Interrupt handler. +pub struct ReceiveInterruptHandler {} + +impl interrupt::Handler for ReceiveInterruptHandler { + unsafe fn on_interrupt() { + if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { + debug!("RX SYS evt"); + sys::Sys::evt_handler(); + } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) { + debug!("RX BLE evt"); + ble::Ble::evt_handler(); + } + + STATE.signal(()); + } +} + +pub struct TransmitInterruptHandler {} + +impl interrupt::Handler for TransmitInterruptHandler { + unsafe fn on_interrupt() { + if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { + debug!("TX SYS cmd rsp"); + let cc = sys::Sys::cmd_evt_handler(); + + LAST_CC_EVT.signal(cc); + } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) { + debug!("TX MM release"); + mm::MemoryManager::free_buf_handler(); + } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL) { + debug!("TX HCI acl"); + ble::Ble::acl_data_handler(); + } + + STATE.signal(()); + } +} + +#[link_section = "TL_REF_TABLE"] +pub static mut TL_REF_TABLE: MaybeUninit = MaybeUninit::uninit(); + +#[link_section = "MB_MEM1"] +static mut TL_DEVICE_INFO_TABLE: MaybeUninit = MaybeUninit::uninit(); + +#[link_section = "MB_MEM1"] +static mut TL_BLE_TABLE: MaybeUninit = MaybeUninit::uninit(); + +#[link_section = "MB_MEM1"] +static mut TL_THREAD_TABLE: MaybeUninit = MaybeUninit::uninit(); + +#[link_section = "MB_MEM1"] +static mut TL_SYS_TABLE: MaybeUninit = MaybeUninit::uninit(); + +#[link_section = "MB_MEM1"] +static mut TL_MEM_MANAGER_TABLE: MaybeUninit = MaybeUninit::uninit(); + +#[link_section = "MB_MEM1"] +static mut TL_TRACES_TABLE: MaybeUninit = MaybeUninit::uninit(); + +#[link_section = "MB_MEM1"] +static mut TL_MAC_802_15_4_TABLE: MaybeUninit = MaybeUninit::uninit(); + +#[link_section = "MB_MEM2"] +static mut FREE_BUF_QUEUE: MaybeUninit = MaybeUninit::uninit(); + +// Not in shared RAM +static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit = MaybeUninit::uninit(); + +#[allow(dead_code)] // Not used currently but reserved +#[link_section = "MB_MEM2"] +static mut TRACES_EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); + +type PacketHeader = LinkedListNode; + +const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::(); +const TL_EVT_HEADER_SIZE: usize = 3; +const TL_CS_EVT_SIZE: usize = core::mem::size_of::(); + +#[link_section = "MB_MEM2"] +static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> = + MaybeUninit::uninit(); + +#[link_section = "MB_MEM2"] +static mut EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); + +#[link_section = "MB_MEM2"] +static mut SYSTEM_EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); + +#[link_section = "MB_MEM2"] +pub static mut SYS_CMD_BUF: MaybeUninit = MaybeUninit::uninit(); + +/** + * Queue length of BLE Event + * This parameter defines the number of asynchronous events that can be stored in the HCI layer before + * being reported to the application. When a command is sent to the BLE core coprocessor, the HCI layer + * is waiting for the event with the Num_HCI_Command_Packets set to 1. The receive queue shall be large + * enough to store all asynchronous events received in between. + * When CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE is set to 27, this allow to store three 255 bytes long asynchronous events + * between the HCI command and its event. + * This parameter depends on the value given to CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE. When the queue size is to small, + * the system may hang if the queue is full with asynchronous events and the HCI layer is still waiting + * for a CC/CS event, In that case, the notification TL_BLE_HCI_ToNot() is called to indicate + * to the application a HCI command did not receive its command event within 30s (Default HCI Timeout). + */ +const CFG_TLBLE_EVT_QUEUE_LENGTH: usize = 5; +const CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255; +const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE; + +const fn divc(x: usize, y: usize) -> usize { + ((x) + (y) - 1) / (y) +} + +const POOL_SIZE: usize = CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); + +#[link_section = "MB_MEM2"] +static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit(); + +#[link_section = "MB_MEM2"] +static mut SYS_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> = + MaybeUninit::uninit(); + +#[link_section = "MB_MEM2"] +static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> = + MaybeUninit::uninit(); + +#[link_section = "MB_MEM2"] +static mut BLE_CMD_BUFFER: MaybeUninit = MaybeUninit::uninit(); + +#[link_section = "MB_MEM2"] +// fuck these "magic" numbers from ST ---v---v +static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); + +/// current event that is produced during IPCC IRQ handler execution +/// on SYS channel +static EVT_CHANNEL: Channel = Channel::new(); + +/// last received Command Complete event +static LAST_CC_EVT: Signal = Signal::new(); + +static STATE: Signal = Signal::new(); + +pub struct TlMbox<'d> { + _ipcc: PeripheralRef<'d, IPCC>, +} + +impl<'d> TlMbox<'d> { + pub fn init( + ipcc: impl Peripheral

+ 'd, + _irqs: impl interrupt::Binding + + interrupt::Binding, + config: Config, + ) -> Self { + into_ref!(ipcc); + + unsafe { + TL_REF_TABLE = MaybeUninit::new(RefTable { + device_info_table: TL_DEVICE_INFO_TABLE.as_mut_ptr(), + ble_table: TL_BLE_TABLE.as_ptr(), + thread_table: TL_THREAD_TABLE.as_ptr(), + sys_table: TL_SYS_TABLE.as_ptr(), + mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), + traces_table: TL_TRACES_TABLE.as_ptr(), + mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), + }); + + TL_SYS_TABLE = MaybeUninit::zeroed(); + TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed(); + TL_BLE_TABLE = MaybeUninit::zeroed(); + TL_THREAD_TABLE = MaybeUninit::zeroed(); + TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed(); + TL_TRACES_TABLE = MaybeUninit::zeroed(); + TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed(); + + EVT_POOL = MaybeUninit::zeroed(); + SYS_SPARE_EVT_BUF = MaybeUninit::zeroed(); + BLE_SPARE_EVT_BUF = MaybeUninit::zeroed(); + + CS_BUFFER = MaybeUninit::zeroed(); + BLE_CMD_BUFFER = MaybeUninit::zeroed(); + HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed(); + } + + Ipcc::enable(config); + + sys::Sys::enable(); + ble::Ble::enable(); + mm::MemoryManager::enable(); + + // enable interrupts + interrupt::IPCC_C1_RX::unpend(); + interrupt::IPCC_C1_TX::unpend(); + + unsafe { interrupt::IPCC_C1_RX::enable() }; + unsafe { interrupt::IPCC_C1_TX::enable() }; + + 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 + } + } + + /// picks single [`EvtBox`] from internal event queue. + /// + /// Internal event queu is populated in IPCC_RX_IRQ handler + pub fn dequeue_event(&mut self) -> Option { + EVT_CHANNEL.try_recv().ok() + } + + /// retrieves last Command Complete event and removes it from mailbox + pub fn pop_last_cc_evt(&mut self) -> Option { + if LAST_CC_EVT.signaled() { + let cc = block_on(LAST_CC_EVT.wait()); + LAST_CC_EVT.reset(); + Some(cc) + } else { + None + } + } +} diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs new file mode 100644 index 000000000..ed13b0dbf --- /dev/null +++ b/embassy-stm32-wpan/src/mm.rs @@ -0,0 +1,75 @@ +//! Memory manager routines + +use core::mem::MaybeUninit; + +use embassy_stm32::ipcc::Ipcc; + +use crate::evt::EvtPacket; +use crate::tables::MemManagerTable; +use crate::unsafe_linked_list::LinkedListNode; +use crate::{ + channels, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF, + TL_MEM_MANAGER_TABLE, TL_REF_TABLE, +}; + +pub(super) struct MemoryManager; + +impl MemoryManager { + pub fn enable() { + unsafe { + LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); + LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); + + TL_MEM_MANAGER_TABLE = MaybeUninit::new(MemManagerTable { + spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), + spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), + blepool: EVT_POOL.as_ptr().cast(), + blepoolsize: POOL_SIZE as u32, + pevt_free_buffer_queue: FREE_BUF_QUEUE.as_mut_ptr(), + traces_evt_pool: core::ptr::null(), + tracespoolsize: 0, + }); + } + } + + pub fn evt_drop(evt: *mut EvtPacket) { + unsafe { + let list_node = evt.cast(); + + LinkedListNode::insert_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); + + let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + + // postpone event buffer freeing to IPCC interrupt handler + if channel_is_busy { + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); + } else { + Self::send_free_buf(); + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + } + } + } + + /// gives free event buffers back to CPU2 from local buffer queue + pub fn send_free_buf() { + unsafe { + let mut node_ptr = core::ptr::null_mut(); + let node_ptr_ptr: *mut _ = &mut node_ptr; + + while !LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { + LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), node_ptr_ptr); + LinkedListNode::insert_tail( + (*(*TL_REF_TABLE.as_ptr()).mem_manager_table).pevt_free_buffer_queue, + node_ptr, + ); + } + } + } + + /// free buffer channel interrupt handler + pub fn free_buf_handler() { + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false); + Self::send_free_buf(); + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); + } +} diff --git a/embassy-stm32-wpan/src/rc.rs b/embassy-stm32-wpan/src/rc.rs new file mode 100644 index 000000000..aae2265ed --- /dev/null +++ b/embassy-stm32-wpan/src/rc.rs @@ -0,0 +1,50 @@ +use crate::ble::Ble; +use crate::consts::TlPacketType; +use crate::{shci, TlMbox, STATE}; + +pub struct RadioCoprocessor<'d> { + mbox: TlMbox<'d>, + rx_buf: [u8; 500], +} + +impl<'d> RadioCoprocessor<'d> { + pub fn new(mbox: TlMbox<'d>) -> Self { + Self { + mbox, + rx_buf: [0u8; 500], + } + } + + pub fn write(&self, buf: &[u8]) { + let cmd_code = buf[0]; + let cmd = TlPacketType::try_from(cmd_code).unwrap(); + + match &cmd { + TlPacketType::BleCmd => Ble::ble_send_cmd(buf), + _ => todo!(), + } + } + + pub async fn read(&mut self) -> &[u8] { + loop { + STATE.wait().await; + + while let Some(evt) = self.mbox.dequeue_event() { + let event = evt.evt(); + + evt.write(&mut self.rx_buf).unwrap(); + + if event.kind() == 18 { + shci::shci_ble_init(Default::default()); + self.rx_buf[0] = 0x04; + } + } + + if self.mbox.pop_last_cc_evt().is_some() { + continue; + } + + return &self.rx_buf; + } + } +} diff --git a/embassy-stm32-wpan/src/shci.rs b/embassy-stm32-wpan/src/shci.rs new file mode 100644 index 000000000..4f4d08886 --- /dev/null +++ b/embassy-stm32-wpan/src/shci.rs @@ -0,0 +1,100 @@ +use super::cmd::CmdPacket; +use super::consts::TlPacketType; +use super::{sys, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE}; + +const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66; + +#[derive(Debug, Clone, Copy)] +#[repr(C, packed)] +pub struct ShciBleInitCmdParam { + /// NOT USED CURRENTLY + pub p_ble_buffer_address: u32, + + /// Size of the Buffer allocated in pBleBufferAddress + pub ble_buffer_size: u32, + + pub num_attr_record: u16, + pub num_attr_serv: u16, + pub attr_value_arr_size: u16, + pub num_of_links: u8, + pub extended_packet_length_enable: u8, + pub pr_write_list_size: u8, + pub mb_lock_count: u8, + + pub att_mtu: u16, + pub slave_sca: u16, + pub master_sca: u8, + pub ls_source: u8, + pub max_conn_event_length: u32, + pub hs_startup_time: u16, + pub viterbi_enable: u8, + pub ll_only: u8, + pub hw_version: u8, +} + +impl Default for ShciBleInitCmdParam { + fn default() -> Self { + Self { + p_ble_buffer_address: 0, + ble_buffer_size: 0, + num_attr_record: 68, + num_attr_serv: 8, + attr_value_arr_size: 1344, + num_of_links: 2, + extended_packet_length_enable: 1, + pr_write_list_size: 0x3A, + mb_lock_count: 0x79, + att_mtu: 156, + slave_sca: 500, + master_sca: 0, + ls_source: 1, + max_conn_event_length: 0xFFFFFFFF, + hs_startup_time: 0x148, + viterbi_enable: 1, + ll_only: 0, + hw_version: 0, + } + } +} + +#[derive(Debug, Clone, Copy, Default)] +#[repr(C, packed)] +pub struct ShciHeader { + metadata: [u32; 3], +} + +#[derive(Debug, Clone, Copy)] +#[repr(C, packed)] +pub struct ShciBleInitCmdPacket { + header: ShciHeader, + param: ShciBleInitCmdParam, +} + +pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE; +#[allow(dead_code)] // Not used currently but reserved +const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; + +pub fn shci_ble_init(param: ShciBleInitCmdParam) { + debug!("sending SHCI"); + + let mut packet = ShciBleInitCmdPacket { + header: ShciHeader::default(), + param, + }; + + let packet_ptr: *mut _ = &mut packet; + + unsafe { + let cmd_ptr: *mut CmdPacket = packet_ptr.cast(); + + (*cmd_ptr).cmdserial.cmd.cmd_code = SCHI_OPCODE_BLE_INIT; + (*cmd_ptr).cmdserial.cmd.payload_len = core::mem::size_of::() as u8; + + let mut p_cmd_buffer = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; + core::ptr::write(p_cmd_buffer, *cmd_ptr); + + p_cmd_buffer.cmdserial.ty = TlPacketType::SysCmd as u8; + + sys::Sys::send_cmd(); + } +} diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs new file mode 100644 index 000000000..a19d12d27 --- /dev/null +++ b/embassy-stm32-wpan/src/sys.rs @@ -0,0 +1,70 @@ +use core::mem::MaybeUninit; + +use embassy_stm32::ipcc::Ipcc; + +use crate::cmd::{CmdPacket, CmdSerial}; +use crate::evt::{CcEvt, EvtBox, EvtSerial}; +use crate::tables::SysTable; +use crate::unsafe_linked_list::LinkedListNode; +use crate::{channels, EVT_CHANNEL, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; + +pub struct Sys; + +impl Sys { + pub fn enable() { + unsafe { + LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); + + TL_SYS_TABLE = MaybeUninit::new(SysTable { + pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), + sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), + }) + } + + Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true); + } + + pub fn cmd_evt_handler() -> CcEvt { + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, false); + + // ST's command response data structure is really convoluted. + // + // for command response events on SYS channel, the header is missing + // and one should: + // 1. interpret the content of CMD_BUFFER as CmdPacket + // 2. Access CmdPacket's cmdserial field and interpret its content as EvtSerial + // 3. Access EvtSerial's evt field (as Evt) and interpret its payload as CcEvt + // 4. CcEvt type is the actual SHCI response + // 5. profit + unsafe { + let pcmd: *const CmdPacket = (*TL_SYS_TABLE.as_ptr()).pcmd_buffer; + let cmd_serial: *const CmdSerial = &(*pcmd).cmdserial; + let evt_serial: *const EvtSerial = cmd_serial.cast(); + let cc: *const CcEvt = (*evt_serial).evt.payload.as_ptr().cast(); + *cc + } + } + + pub fn evt_handler() { + unsafe { + let mut node_ptr = core::ptr::null_mut(); + let node_ptr_ptr: *mut _ = &mut node_ptr; + + while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { + LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); + + let event = node_ptr.cast(); + let event = EvtBox::new(event); + + EVT_CHANNEL.try_send(event).unwrap(); + } + } + + Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); + } + + pub fn send_cmd() { + Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); + Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); + } +} diff --git a/embassy-stm32-wpan/src/tables.rs b/embassy-stm32-wpan/src/tables.rs new file mode 100644 index 000000000..151216958 --- /dev/null +++ b/embassy-stm32-wpan/src/tables.rs @@ -0,0 +1,175 @@ +use bit_field::BitField; + +use crate::cmd::{AclDataPacket, CmdPacket}; +use crate::unsafe_linked_list::LinkedListNode; + +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +pub struct SafeBootInfoTable { + version: u32, +} + +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +pub struct RssInfoTable { + pub version: u32, + pub memory_size: u32, + pub rss_info: u32, +} + +/** + * Version + * [0:3] = Build - 0: Untracked - 15:Released - x: Tracked version + * [4:7] = branch - 0: Mass Market - x: ... + * [8:15] = Subversion + * [16:23] = Version minor + * [24:31] = Version major + * + * Memory Size + * [0:7] = Flash ( Number of 4k sector) + * [8:15] = Reserved ( Shall be set to 0 - may be used as flash extension ) + * [16:23] = SRAM2b ( Number of 1k sector) + * [24:31] = SRAM2a ( Number of 1k sector) + */ +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +pub struct WirelessFwInfoTable { + pub version: u32, + pub memory_size: u32, + pub thread_info: u32, + pub ble_info: u32, +} + +impl WirelessFwInfoTable { + pub fn version_major(&self) -> u8 { + let version = self.version; + (version.get_bits(24..31) & 0xff) as u8 + } + + pub fn version_minor(&self) -> u8 { + let version = self.version; + (version.clone().get_bits(16..23) & 0xff) as u8 + } + + pub fn subversion(&self) -> u8 { + let version = self.version; + (version.clone().get_bits(8..15) & 0xff) as u8 + } + + /// Size of FLASH, expressed in number of 4K sectors. + pub fn flash_size(&self) -> u8 { + let memory_size = self.memory_size; + (memory_size.clone().get_bits(0..7) & 0xff) as u8 + } + + /// Size of SRAM2a, expressed in number of 1K sectors. + pub fn sram2a_size(&self) -> u8 { + let memory_size = self.memory_size; + (memory_size.clone().get_bits(24..31) & 0xff) as u8 + } + + /// Size of SRAM2b, expressed in number of 1K sectors. + pub fn sram2b_size(&self) -> u8 { + let memory_size = self.memory_size; + (memory_size.clone().get_bits(16..23) & 0xff) as u8 + } +} + +#[derive(Debug, Clone)] +#[repr(C, align(4))] +pub struct DeviceInfoTable { + pub safe_boot_info_table: SafeBootInfoTable, + pub rss_info_table: RssInfoTable, + pub wireless_fw_info_table: WirelessFwInfoTable, +} + +#[derive(Debug)] +#[repr(C, align(4))] +pub struct BleTable { + pub pcmd_buffer: *mut CmdPacket, + pub pcs_buffer: *const u8, + pub pevt_queue: *const u8, + pub phci_acl_data_buffer: *mut AclDataPacket, +} + +#[derive(Debug)] +#[repr(C, align(4))] +pub struct ThreadTable { + pub nostack_buffer: *const u8, + pub clicmdrsp_buffer: *const u8, + pub otcmdrsp_buffer: *const u8, +} + +// TODO: use later +#[derive(Debug)] +#[repr(C, align(4))] +pub struct LldTestsTable { + pub clicmdrsp_buffer: *const u8, + pub m0cmd_buffer: *const u8, +} + +// TODO: use later +#[derive(Debug)] +#[repr(C, align(4))] +pub struct BleLldTable { + pub cmdrsp_buffer: *const u8, + pub m0cmd_buffer: *const u8, +} + +// TODO: use later +#[derive(Debug)] +#[repr(C, align(4))] +pub struct ZigbeeTable { + pub notif_m0_to_m4_buffer: *const u8, + pub appli_cmd_m4_to_m0_bufer: *const u8, + pub request_m0_to_m4_buffer: *const u8, +} + +#[derive(Debug)] +#[repr(C, align(4))] +pub struct SysTable { + pub pcmd_buffer: *mut CmdPacket, + pub sys_queue: *const LinkedListNode, +} + +#[derive(Debug)] +#[repr(C, align(4))] +pub struct MemManagerTable { + pub spare_ble_buffer: *const u8, + pub spare_sys_buffer: *const u8, + + pub blepool: *const u8, + pub blepoolsize: u32, + + pub pevt_free_buffer_queue: *mut LinkedListNode, + + pub traces_evt_pool: *const u8, + pub tracespoolsize: u32, +} + +#[derive(Debug)] +#[repr(C, align(4))] +pub struct TracesTable { + pub traces_queue: *const u8, +} + +#[derive(Debug)] +#[repr(C, align(4))] +pub struct Mac802_15_4Table { + pub p_cmdrsp_buffer: *const u8, + pub p_notack_buffer: *const u8, + pub evt_queue: *const u8, +} + +/// Reference table. Contains pointers to all other tables. +#[derive(Debug, Copy, Clone)] +#[repr(C)] +pub struct RefTable { + pub device_info_table: *const DeviceInfoTable, + pub ble_table: *const BleTable, + pub thread_table: *const ThreadTable, + pub sys_table: *const SysTable, + pub mem_manager_table: *const MemManagerTable, + pub traces_table: *const TracesTable, + pub mac_802_15_4_table: *const Mac802_15_4Table, +} diff --git a/embassy-stm32-wpan/src/unsafe_linked_list.rs b/embassy-stm32-wpan/src/unsafe_linked_list.rs new file mode 100644 index 000000000..52c106fa2 --- /dev/null +++ b/embassy-stm32-wpan/src/unsafe_linked_list.rs @@ -0,0 +1,128 @@ +//! Unsafe linked list. +//! Translated from ST's C by `c2rust` tool. + +#![allow( + dead_code, + mutable_transmutes, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] + +use cortex_m::interrupt; + +#[derive(Copy, Clone)] +#[repr(C, packed(4))] +pub struct LinkedListNode { + pub next: *mut LinkedListNode, + pub prev: *mut LinkedListNode, +} + +impl Default for LinkedListNode { + fn default() -> Self { + LinkedListNode { + next: core::ptr::null_mut(), + prev: core::ptr::null_mut(), + } + } +} + +impl LinkedListNode { + pub unsafe fn init_head(mut list_head: *mut LinkedListNode) { + (*list_head).next = list_head; + (*list_head).prev = list_head; + } + + pub unsafe fn is_empty(mut list_head: *mut LinkedListNode) -> bool { + interrupt::free(|_| ((*list_head).next) == list_head) + } + + pub unsafe fn insert_head(mut list_head: *mut LinkedListNode, mut node: *mut LinkedListNode) { + interrupt::free(|_| { + (*node).next = (*list_head).next; + (*node).prev = list_head; + (*list_head).next = node; + (*(*node).next).prev = node; + }); + } + + pub unsafe fn insert_tail(mut list_head: *mut LinkedListNode, mut node: *mut LinkedListNode) { + interrupt::free(|_| { + (*node).next = list_head; + (*node).prev = (*list_head).prev; + (*list_head).prev = node; + (*(*node).prev).next = node; + }); + } + + /// Remove `node` from the linked list + pub unsafe fn remove_node(mut node: *mut LinkedListNode) { + interrupt::free(|_| { + (*(*node).prev).next = (*node).next; + (*(*node).next).prev = (*node).prev; + }); + } + + /// Remove `list_head` into `node` + pub unsafe fn remove_head(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { + interrupt::free(|_| { + *node = (*list_head).next; + Self::remove_node((*list_head).next); + }); + } + + /// Remove `list_tail` into `node` + pub unsafe fn remove_tail(mut list_tail: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { + interrupt::free(|_| { + *node = (*list_tail).prev; + Self::remove_node((*list_tail).prev); + }); + } + + pub unsafe fn insert_node_after(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) { + interrupt::free(|_| { + (*node).next = (*ref_node).next; + (*node).prev = ref_node; + (*ref_node).next = node; + (*(*node).next).prev = node; + }); + } + + pub unsafe fn insert_node_before(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) { + interrupt::free(|_| { + (*node).next = ref_node; + (*node).prev = (*ref_node).prev; + (*ref_node).prev = node; + (*(*node).prev).next = node; + }); + } + + pub unsafe fn get_size(mut list_head: *mut LinkedListNode) -> usize { + interrupt::free(|_| { + let mut size = 0; + let mut temp: *mut LinkedListNode = core::ptr::null_mut::(); + + temp = (*list_head).next; + while temp != list_head { + size += 1; + temp = (*temp).next + } + + size + }) + } + + pub unsafe fn get_next_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { + interrupt::free(|_| { + *node = (*ref_node).next; + }); + } + + pub unsafe fn get_prev_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { + interrupt::free(|_| { + *node = (*ref_node).prev; + }); + } +} diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs new file mode 100644 index 000000000..8bb0774b8 --- /dev/null +++ b/embassy-stm32/src/ipcc.rs @@ -0,0 +1,234 @@ +use self::sealed::Instance; +use crate::peripherals::IPCC; +use crate::rcc::sealed::RccPeripheral; + +#[non_exhaustive] +#[derive(Clone, Copy, Default)] +pub struct Config { + // TODO: add IPCC peripheral configuration, if any, here + // reserved for future use +} + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub enum IpccChannel { + Channel1 = 0, + Channel2 = 1, + Channel3 = 2, + Channel4 = 3, + Channel5 = 4, + Channel6 = 5, +} + +pub mod sealed { + pub trait Instance: crate::rcc::RccPeripheral { + fn regs() -> crate::pac::ipcc::Ipcc; + fn set_cpu2(enabled: bool); + } +} + +pub struct Ipcc; + +impl Ipcc { + pub fn enable(_config: Config) { + IPCC::enable(); + IPCC::reset(); + IPCC::set_cpu2(true); + + unsafe { _configure_pwr() }; + + let regs = IPCC::regs(); + + unsafe { + regs.cpu(0).cr().modify(|w| { + w.set_rxoie(true); + w.set_txfie(true); + }) + } + } + + pub fn c1_set_rx_channel(channel: IpccChannel, enabled: bool) { + let regs = IPCC::regs(); + + // If bit is set to 1 then interrupt is disabled + unsafe { regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, !enabled)) } + } + + pub fn c1_get_rx_channel(channel: IpccChannel) -> bool { + let regs = IPCC::regs(); + + // If bit is set to 1 then interrupt is disabled + unsafe { !regs.cpu(0).mr().read().chom(channel as usize) } + } + + #[allow(dead_code)] + pub fn c2_set_rx_channel(channel: IpccChannel, enabled: bool) { + let regs = IPCC::regs(); + + // If bit is set to 1 then interrupt is disabled + unsafe { regs.cpu(1).mr().modify(|w| w.set_chom(channel as usize, !enabled)) } + } + + #[allow(dead_code)] + pub fn c2_get_rx_channel(channel: IpccChannel) -> bool { + let regs = IPCC::regs(); + + // If bit is set to 1 then interrupt is disabled + unsafe { !regs.cpu(1).mr().read().chom(channel as usize) } + } + + pub fn c1_set_tx_channel(channel: IpccChannel, enabled: bool) { + let regs = IPCC::regs(); + + // If bit is set to 1 then interrupt is disabled + unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) } + } + + pub fn c1_get_tx_channel(channel: IpccChannel) -> bool { + let regs = IPCC::regs(); + + // If bit is set to 1 then interrupt is disabled + unsafe { !regs.cpu(0).mr().read().chfm(channel as usize) } + } + + #[allow(dead_code)] + pub fn c2_set_tx_channel(channel: IpccChannel, enabled: bool) { + let regs = IPCC::regs(); + + // If bit is set to 1 then interrupt is disabled + unsafe { regs.cpu(1).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) } + } + + #[allow(dead_code)] + pub fn c2_get_tx_channel(channel: IpccChannel) -> bool { + let regs = IPCC::regs(); + + // If bit is set to 1 then interrupt is disabled + unsafe { !regs.cpu(1).mr().read().chfm(channel as usize) } + } + + /// clears IPCC receive channel status for CPU1 + pub fn c1_clear_flag_channel(channel: IpccChannel) { + let regs = IPCC::regs(); + + unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) } + } + + #[allow(dead_code)] + /// clears IPCC receive channel status for CPU2 + pub fn c2_clear_flag_channel(channel: IpccChannel) { + let regs = IPCC::regs(); + + unsafe { regs.cpu(1).scr().write(|w| w.set_chc(channel as usize, true)) } + } + + pub fn c1_set_flag_channel(channel: IpccChannel) { + let regs = IPCC::regs(); + + unsafe { regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)) } + } + + #[allow(dead_code)] + pub fn c2_set_flag_channel(channel: IpccChannel) { + let regs = IPCC::regs(); + + unsafe { regs.cpu(1).scr().write(|w| w.set_chs(channel as usize, true)) } + } + + pub fn c1_is_active_flag(channel: IpccChannel) -> bool { + let regs = IPCC::regs(); + + unsafe { regs.cpu(0).sr().read().chf(channel as usize) } + } + + pub fn c2_is_active_flag(channel: IpccChannel) -> bool { + let regs = IPCC::regs(); + + unsafe { regs.cpu(1).sr().read().chf(channel as usize) } + } + + pub fn is_tx_pending(channel: IpccChannel) -> bool { + !Self::c1_is_active_flag(channel) && Self::c1_get_tx_channel(channel) + } + + pub fn is_rx_pending(channel: IpccChannel) -> bool { + Self::c2_is_active_flag(channel) && Self::c1_get_rx_channel(channel) + } +} + +impl sealed::Instance for crate::peripherals::IPCC { + fn regs() -> crate::pac::ipcc::Ipcc { + crate::pac::IPCC + } + + fn set_cpu2(enabled: bool) { + unsafe { crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)) } + } +} + +unsafe fn _configure_pwr() { + let pwr = crate::pac::PWR; + let rcc = crate::pac::RCC; + + rcc.cfgr().modify(|w| w.set_stopwuck(true)); + + pwr.cr1().modify(|w| w.set_dbp(true)); + pwr.cr1().modify(|w| w.set_dbp(true)); + + // configure LSE + rcc.bdcr().modify(|w| w.set_lseon(true)); + + // select system clock source = PLL + // set PLL coefficients + // m: 2, + // n: 12, + // r: 3, + // q: 4, + // p: 3, + let src_bits = 0b11; + let pllp = (3 - 1) & 0b11111; + let pllq = (4 - 1) & 0b111; + let pllr = (3 - 1) & 0b111; + let plln = 12 & 0b1111111; + let pllm = (2 - 1) & 0b111; + rcc.pllcfgr().modify(|w| { + w.set_pllsrc(src_bits); + w.set_pllm(pllm); + w.set_plln(plln); + w.set_pllr(pllr); + w.set_pllp(pllp); + w.set_pllpen(true); + w.set_pllq(pllq); + w.set_pllqen(true); + }); + // enable PLL + rcc.cr().modify(|w| w.set_pllon(true)); + rcc.cr().write(|w| w.set_hsion(false)); + // while !rcc.cr().read().pllrdy() {} + + // configure SYSCLK mux to use PLL clocl + rcc.cfgr().modify(|w| w.set_sw(0b11)); + + // configure CPU1 & CPU2 dividers + rcc.cfgr().modify(|w| w.set_hpre(0)); // not divided + rcc.extcfgr().modify(|w| { + w.set_c2hpre(0b1000); // div2 + w.set_shdhpre(0); // not divided + }); + + // apply APB1 / APB2 values + rcc.cfgr().modify(|w| { + w.set_ppre1(0b000); // not divided + w.set_ppre2(0b000); // not divided + }); + + // TODO: required + // set RF wake-up clock = LSE + rcc.csr().modify(|w| w.set_rfwkpsel(0b01)); + + // set LPTIM1 & LPTIM2 clock source + rcc.ccipr().modify(|w| { + w.set_lptim1sel(0b00); // PCLK + w.set_lptim2sel(0b00); // PCLK + }); +} diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 75d8af3dd..8c13774a0 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -41,6 +41,8 @@ pub mod crc; pub mod flash; #[cfg(all(spi_v1, rcc_f4))] pub mod i2s; +#[cfg(stm32wb)] +pub mod ipcc; pub mod pwm; #[cfg(quadspi)] pub mod qspi; @@ -52,8 +54,6 @@ pub mod rtc; pub mod sdmmc; #[cfg(spi)] pub mod spi; -#[cfg(stm32wb)] -pub mod tl_mbox; #[cfg(usart)] pub mod usart; #[cfg(usb)] diff --git a/embassy-stm32/src/tl_mbox/ble.rs b/embassy-stm32/src/tl_mbox/ble.rs deleted file mode 100644 index 45bf81ef2..000000000 --- a/embassy-stm32/src/tl_mbox/ble.rs +++ /dev/null @@ -1,81 +0,0 @@ -use embassy_futures::block_on; - -use super::cmd::{CmdPacket, CmdSerial}; -use super::consts::TlPacketType; -use super::evt::EvtBox; -use super::ipcc::Ipcc; -use super::unsafe_linked_list::LinkedListNode; -use super::{ - channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, HEAPLESS_EVT_QUEUE, TL_BLE_TABLE, - TL_REF_TABLE, -}; - -pub struct Ble; - -impl Ble { - pub(super) fn new() -> Self { - unsafe { - LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); - - TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable { - pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), - pcs_buffer: CS_BUFFER.as_ptr().cast(), - pevt_queue: EVT_QUEUE.as_ptr().cast(), - phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(), - }); - } - - Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true); - - Ble - } - - pub(super) fn evt_handler() { - unsafe { - let mut node_ptr = core::ptr::null_mut(); - let node_ptr_ptr: *mut _ = &mut node_ptr; - - while !LinkedListNode::is_empty(EVT_QUEUE.as_mut_ptr()) { - LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); - - let event = node_ptr.cast(); - let event = EvtBox::new(event); - - block_on(HEAPLESS_EVT_QUEUE.send(event)); - } - } - - Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL); - } - - pub(super) fn acl_data_handler(&self) { - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, false); - - // TODO: ACL data ack to the user - } - - pub fn send_cmd(buf: &[u8]) { - unsafe { - let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; - let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmdserial; - let pcmd_serial_buf: *mut u8 = pcmd_serial.cast(); - - core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len()); - - let mut cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; - cmd_packet.cmdserial.ty = TlPacketType::BleCmd as u8; - } - - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL); - } - - #[allow(dead_code)] // Not used currently but reserved - pub(super) fn send_acl_data() { - let cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; - - cmd_packet.acl_data_serial.ty = TlPacketType::AclData as u8; - - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL); - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, true); - } -} diff --git a/embassy-stm32/src/tl_mbox/channels.rs b/embassy-stm32/src/tl_mbox/channels.rs deleted file mode 100644 index 25a065ba4..000000000 --- a/embassy-stm32/src/tl_mbox/channels.rs +++ /dev/null @@ -1,104 +0,0 @@ -//! CPU1 CPU2 -//! | (SYSTEM) | -//! |----HW_IPCC_SYSTEM_CMD_RSP_CHANNEL-------------->| -//! | | -//! |<---HW_IPCC_SYSTEM_EVENT_CHANNEL-----------------| -//! | | -//! | (ZIGBEE) | -//! |----HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL------------>| -//! | | -//! |----HW_IPCC_ZIGBEE_CMD_CLI_CHANNEL-------------->| -//! | | -//! |<---HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL-------| -//! | | -//! |<---HW_IPCC_ZIGBEE_CLI_NOTIF_ACK_CHANNEL---------| -//! | | -//! | (THREAD) | -//! |----HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL----------->| -//! | | -//! |----HW_IPCC_THREAD_CLI_CMD_CHANNEL-------------->| -//! | | -//! |<---HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL------| -//! | | -//! |<---HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL--| -//! | | -//! | (BLE) | -//! |----HW_IPCC_BLE_CMD_CHANNEL--------------------->| -//! | | -//! |----HW_IPCC_HCI_ACL_DATA_CHANNEL---------------->| -//! | | -//! |<---HW_IPCC_BLE_EVENT_CHANNEL--------------------| -//! | | -//! | (BLE LLD) | -//! |----HW_IPCC_BLE_LLD_CMD_CHANNEL----------------->| -//! | | -//! |<---HW_IPCC_BLE_LLD_RSP_CHANNEL------------------| -//! | | -//! |<---HW_IPCC_BLE_LLD_M0_CMD_CHANNEL---------------| -//! | | -//! | (MAC) | -//! |----HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL-------->| -//! | | -//! |<---HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL| -//! | | -//! | (BUFFER) | -//! |----HW_IPCC_MM_RELEASE_BUFFER_CHANNE------------>| -//! | | -//! | (TRACE) | -//! |<----HW_IPCC_TRACES_CHANNEL----------------------| -//! | | -//! - -pub mod cpu1 { - use crate::tl_mbox::ipcc::IpccChannel; - - // Not used currently but reserved - pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1; - // Not used currently but reserved - pub const IPCC_SYSTEM_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel2; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_THREAD_OT_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_ZIGBEE_CMD_APPLI_CHANNEL: IpccChannel = IpccChannel::Channel3; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_MAC_802_15_4_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; - // Not used currently but reserved - pub const IPCC_MM_RELEASE_BUFFER_CHANNEL: IpccChannel = IpccChannel::Channel4; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_THREAD_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_LLDTESTS_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_BLE_LLD_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_HCI_ACL_DATA_CHANNEL: IpccChannel = IpccChannel::Channel6; -} - -pub mod cpu2 { - use crate::tl_mbox::ipcc::IpccChannel; - - pub const IPCC_BLE_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel1; - pub const IPCC_SYSTEM_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel2; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_THREAD_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_LDDTESTS_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_BLE_LLD_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_TRACES_CHANNEL: IpccChannel = IpccChannel::Channel4; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel5; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_LLDTESTS_CLI_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_BLE_LLD_CLI_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_BLE_LLD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5; - #[allow(dead_code)] // Not used currently but reserved - pub const IPCC_ZIGBEE_M0_REQUEST_CHANNEL: IpccChannel = IpccChannel::Channel5; -} diff --git a/embassy-stm32/src/tl_mbox/cmd.rs b/embassy-stm32/src/tl_mbox/cmd.rs deleted file mode 100644 index 781aa669d..000000000 --- a/embassy-stm32/src/tl_mbox/cmd.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::tl_mbox::evt::{EvtPacket, EvtSerial}; -use crate::tl_mbox::{PacketHeader, TL_EVT_HEADER_SIZE}; - -#[derive(Copy, Clone)] -#[repr(C, packed)] -pub struct Cmd { - pub cmd_code: u16, - pub payload_len: u8, - pub payload: [u8; 255], -} - -impl Default for Cmd { - fn default() -> Self { - Self { - cmd_code: 0, - payload_len: 0, - payload: [0u8; 255], - } - } -} - -#[derive(Copy, Clone, Default)] -#[repr(C, packed)] -pub struct CmdSerial { - pub ty: u8, - pub cmd: Cmd, -} - -#[derive(Copy, Clone, Default)] -#[repr(C, packed)] -pub struct CmdPacket { - pub header: PacketHeader, - pub cmdserial: CmdSerial, -} - -impl CmdPacket { - /// Writes an underlying CmdPacket into the provided buffer. - /// Returns a number of bytes that were written. - /// Returns an error if event kind is unknown or if provided buffer size is not enough. - #[allow(clippy::result_unit_err)] - pub fn write(&self, buf: &mut [u8]) -> Result { - unsafe { - let cmd_ptr: *const CmdPacket = self; - let self_as_evt_ptr: *const EvtPacket = cmd_ptr.cast(); - let evt_serial: *const EvtSerial = &(*self_as_evt_ptr).evt_serial; - - let acl_data: *const AclDataPacket = cmd_ptr.cast(); - let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; - let acl_serial_buf: *const u8 = acl_serial.cast(); - - let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE; - if len > buf.len() { - return Err(()); - } - - core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len); - - Ok(len) - } - } -} - -#[derive(Copy, Clone)] -#[repr(C, packed)] -pub struct AclDataSerial { - pub ty: u8, - pub handle: u16, - pub length: u16, - pub acl_data: [u8; 1], -} - -#[derive(Copy, Clone)] -#[repr(C, packed)] -pub struct AclDataPacket { - pub header: PacketHeader, - pub acl_data_serial: AclDataSerial, -} diff --git a/embassy-stm32/src/tl_mbox/consts.rs b/embassy-stm32/src/tl_mbox/consts.rs deleted file mode 100644 index caf26c06b..000000000 --- a/embassy-stm32/src/tl_mbox/consts.rs +++ /dev/null @@ -1,55 +0,0 @@ -use core::convert::TryFrom; - -#[derive(Debug)] -#[repr(C)] -pub enum TlPacketType { - BleCmd = 0x01, - AclData = 0x02, - BleEvt = 0x04, - - OtCmd = 0x08, - OtRsp = 0x09, - CliCmd = 0x0A, - OtNot = 0x0C, - OtAck = 0x0D, - CliNot = 0x0E, - CliAck = 0x0F, - - SysCmd = 0x10, - SysRsp = 0x11, - SysEvt = 0x12, - - LocCmd = 0x20, - LocRsp = 0x21, - - TracesApp = 0x40, - TracesWl = 0x41, -} - -impl TryFrom for TlPacketType { - type Error = (); - - fn try_from(value: u8) -> Result { - match value { - 0x01 => Ok(TlPacketType::BleCmd), - 0x02 => Ok(TlPacketType::AclData), - 0x04 => Ok(TlPacketType::BleEvt), - 0x08 => Ok(TlPacketType::OtCmd), - 0x09 => Ok(TlPacketType::OtRsp), - 0x0A => Ok(TlPacketType::CliCmd), - 0x0C => Ok(TlPacketType::OtNot), - 0x0D => Ok(TlPacketType::OtAck), - 0x0E => Ok(TlPacketType::CliNot), - 0x0F => Ok(TlPacketType::CliAck), - 0x10 => Ok(TlPacketType::SysCmd), - 0x11 => Ok(TlPacketType::SysRsp), - 0x12 => Ok(TlPacketType::SysEvt), - 0x20 => Ok(TlPacketType::LocCmd), - 0x21 => Ok(TlPacketType::LocRsp), - 0x40 => Ok(TlPacketType::TracesApp), - 0x41 => Ok(TlPacketType::TracesWl), - - _ => Err(()), - } - } -} diff --git a/embassy-stm32/src/tl_mbox/evt.rs b/embassy-stm32/src/tl_mbox/evt.rs deleted file mode 100644 index 77ce7b4ca..000000000 --- a/embassy-stm32/src/tl_mbox/evt.rs +++ /dev/null @@ -1,176 +0,0 @@ -use core::mem::MaybeUninit; - -use super::cmd::{AclDataPacket, AclDataSerial}; -use super::consts::TlPacketType; -use super::mm::MemoryManager; -use super::{PacketHeader, TL_EVT_HEADER_SIZE}; - -/** - * The payload of `Evt` for a command status event - */ -#[derive(Debug, Copy, Clone)] -#[repr(C, packed)] -pub struct CsEvt { - pub status: u8, - pub num_cmd: u8, - pub cmd_code: u16, -} - -/** - * The payload of `Evt` for a command complete event - */ -#[derive(Debug, Copy, Clone, Default)] -#[repr(C, packed)] -pub struct CcEvt { - pub num_cmd: u8, - pub cmd_code: u16, - pub payload: [u8; 1], -} - -impl CcEvt { - pub fn write(&self, buf: &mut [u8]) { - unsafe { - let len = core::mem::size_of::(); - assert!(buf.len() >= len); - - let self_ptr: *const CcEvt = self; - let self_buf_ptr: *const u8 = self_ptr.cast(); - - core::ptr::copy(self_buf_ptr, buf.as_mut_ptr(), len); - } - } -} - -#[derive(Debug, Copy, Clone, Default)] -#[repr(C, packed)] -pub struct AsynchEvt { - sub_evt_code: u16, - payload: [u8; 1], -} - -#[derive(Debug, Copy, Clone, Default)] -#[repr(C, packed)] -pub struct Evt { - pub evt_code: u8, - pub payload_len: u8, - pub payload: [u8; 1], -} - -#[derive(Debug, Copy, Clone, Default)] -#[repr(C, packed)] -pub struct EvtSerial { - pub kind: u8, - pub evt: Evt, -} - -/// This format shall be used for all events (asynchronous and command response) reported -/// by the CPU2 except for the command response of a system command where the header is not there -/// and the format to be used shall be `EvtSerial`. -/// -/// ### Note: -/// Be careful that the asynchronous events reported by the CPU2 on the system channel do -/// include the header and shall use `EvtPacket` format. Only the command response format on the -/// system channel is different. -#[derive(Copy, Clone, Default)] -#[repr(C, packed)] -pub struct EvtPacket { - pub header: PacketHeader, - pub evt_serial: EvtSerial, -} - -impl EvtPacket { - pub fn kind(&self) -> u8 { - self.evt_serial.kind - } - - pub fn evt(&self) -> &Evt { - &self.evt_serial.evt - } -} - -/// smart pointer to the [`EvtPacket`] that will dispose of [`EvtPacket`] buffer automatically -/// on [`Drop`] -#[derive(Debug)] -pub struct EvtBox { - ptr: *mut EvtPacket, -} - -unsafe impl Send for EvtBox {} -impl EvtBox { - pub(super) fn new(ptr: *mut EvtPacket) -> Self { - Self { ptr } - } - - /// copies event data from inner pointer and returns an event structure - pub fn evt(&self) -> EvtPacket { - let mut evt = MaybeUninit::uninit(); - unsafe { - self.ptr.copy_to(evt.as_mut_ptr(), 1); - evt.assume_init() - } - } - - /// writes an underlying [`EvtPacket`] into the provided buffer. - /// Returns the number of bytes that were written. - /// Returns an error if event kind is unknown or if provided buffer size is not enough. - #[allow(clippy::result_unit_err)] - pub fn write(&self, buf: &mut [u8]) -> Result { - unsafe { - let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; - - let evt_data: *const EvtPacket = self.ptr.cast(); - let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; - let evt_serial_buf: *const u8 = evt_serial.cast(); - - let acl_data: *const AclDataPacket = self.ptr.cast(); - let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; - let acl_serial_buf: *const u8 = acl_serial.cast(); - - if let TlPacketType::AclData = evt_kind { - let len = (*acl_serial).length as usize + 5; - if len > buf.len() { - return Err(()); - } - - core::ptr::copy(evt_serial_buf, buf.as_mut_ptr(), len); - - Ok(len) - } else { - let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE; - if len > buf.len() { - return Err(()); - } - - core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len); - - Ok(len) - } - } - } - - /// returns the size of a buffer required to hold this event - #[allow(clippy::result_unit_err)] - pub fn size(&self) -> Result { - unsafe { - let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; - - let evt_data: *const EvtPacket = self.ptr.cast(); - let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; - - let acl_data: *const AclDataPacket = self.ptr.cast(); - let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; - - if let TlPacketType::AclData = evt_kind { - Ok((*acl_serial).length as usize + 5) - } else { - Ok((*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE) - } - } - } -} - -impl Drop for EvtBox { - fn drop(&mut self) { - MemoryManager::evt_drop(self.ptr); - } -} diff --git a/embassy-stm32/src/tl_mbox/hci.rs b/embassy-stm32/src/tl_mbox/hci.rs deleted file mode 100644 index 5bb4ba666..000000000 --- a/embassy-stm32/src/tl_mbox/hci.rs +++ /dev/null @@ -1,60 +0,0 @@ -use super::ble::Ble; -use super::consts::TlPacketType; -use super::evt::CcEvt; -use super::shci::{shci_ble_init, ShciBleInitCmdParam}; -use super::{TlMbox, STATE}; - -pub struct RadioCoprocessor<'d> { - mbox: TlMbox<'d>, - config: ShciBleInitCmdParam, - rx_buffer: [u8; 500], -} - -impl<'d> RadioCoprocessor<'d> { - pub fn new(mbox: TlMbox<'d>, config: ShciBleInitCmdParam) -> Self { - Self { - mbox, - config, - rx_buffer: [0u8; 500], - } - } - - pub fn write(&mut self, params: &[u8]) -> Result<(), ()> { - let cmd_code = params[0]; - let cmd = TlPacketType::try_from(cmd_code)?; - - match cmd { - TlPacketType::BleCmd => Ble::send_cmd(params), - _ => todo!(), - } - - Ok(()) - } - - pub async fn read(&mut self) -> &[u8] { - self.rx_buffer = [0u8; 500]; - - loop { - STATE.wait().await; - - if let Some(evt) = self.mbox.dequeue_event() { - let event = evt.evt(); - evt.write(&mut self.rx_buffer).unwrap(); - - if event.kind() == 18 { - shci_ble_init(self.config); - self.rx_buffer[0] = 0x04; // replace event code with one that is supported by HCI - } - - if let Some(cc) = self.mbox.pop_last_cc_evt() { - - - continue; - } - - let payload_len = self.rx_buffer[2]; - return &self.rx_buffer[..3 + payload_len as usize]; - } - } - } -} diff --git a/embassy-stm32/src/tl_mbox/ipcc.rs b/embassy-stm32/src/tl_mbox/ipcc.rs deleted file mode 100644 index d1ac731ed..000000000 --- a/embassy-stm32/src/tl_mbox/ipcc.rs +++ /dev/null @@ -1,174 +0,0 @@ -use self::sealed::Instance; -use crate::peripherals::IPCC; -use crate::rcc::sealed::RccPeripheral; - -#[non_exhaustive] -#[derive(Clone, Copy, Default)] -pub struct Config { - // TODO: add IPCC peripheral configuration, if any, here - // reserved for future use -} - -#[derive(Debug, Clone, Copy)] -#[repr(C)] -pub enum IpccChannel { - Channel1 = 0, - Channel2 = 1, - Channel3 = 2, - Channel4 = 3, - Channel5 = 4, - Channel6 = 5, -} - -pub mod sealed { - pub trait Instance: crate::rcc::RccPeripheral { - fn regs() -> crate::pac::ipcc::Ipcc; - fn set_cpu2(enabled: bool); - } -} - -pub struct Ipcc; - -impl Ipcc { - pub fn enable(_config: Config) { - IPCC::enable(); - IPCC::reset(); - IPCC::set_cpu2(true); - - unsafe { _configure_pwr() }; - - let regs = IPCC::regs(); - - unsafe { - regs.cpu(0).cr().modify(|w| { - w.set_rxoie(true); - w.set_txfie(true); - }) - } - } - - pub fn c1_set_rx_channel(channel: IpccChannel, enabled: bool) { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, !enabled)) } - } - - pub fn c1_get_rx_channel(channel: IpccChannel) -> bool { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { !regs.cpu(0).mr().read().chom(channel as usize) } - } - - #[allow(dead_code)] - pub fn c2_set_rx_channel(channel: IpccChannel, enabled: bool) { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { regs.cpu(1).mr().modify(|w| w.set_chom(channel as usize, !enabled)) } - } - - #[allow(dead_code)] - pub fn c2_get_rx_channel(channel: IpccChannel) -> bool { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { !regs.cpu(1).mr().read().chom(channel as usize) } - } - - pub fn c1_set_tx_channel(channel: IpccChannel, enabled: bool) { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) } - } - - pub fn c1_get_tx_channel(channel: IpccChannel) -> bool { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { !regs.cpu(0).mr().read().chfm(channel as usize) } - } - - #[allow(dead_code)] - pub fn c2_set_tx_channel(channel: IpccChannel, enabled: bool) { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { regs.cpu(1).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) } - } - - #[allow(dead_code)] - pub fn c2_get_tx_channel(channel: IpccChannel) -> bool { - let regs = IPCC::regs(); - - // If bit is set to 1 then interrupt is disabled - unsafe { !regs.cpu(1).mr().read().chfm(channel as usize) } - } - - /// clears IPCC receive channel status for CPU1 - pub fn c1_clear_flag_channel(channel: IpccChannel) { - let regs = IPCC::regs(); - - unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) } - } - - #[allow(dead_code)] - /// clears IPCC receive channel status for CPU2 - pub fn c2_clear_flag_channel(channel: IpccChannel) { - let regs = IPCC::regs(); - - unsafe { regs.cpu(1).scr().write(|w| w.set_chc(channel as usize, true)) } - } - - pub fn c1_set_flag_channel(channel: IpccChannel) { - let regs = IPCC::regs(); - - unsafe { regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)) } - } - - #[allow(dead_code)] - pub fn c2_set_flag_channel(channel: IpccChannel) { - let regs = IPCC::regs(); - - unsafe { regs.cpu(1).scr().write(|w| w.set_chs(channel as usize, true)) } - } - - pub fn c1_is_active_flag(channel: IpccChannel) -> bool { - let regs = IPCC::regs(); - - unsafe { regs.cpu(0).sr().read().chf(channel as usize) } - } - - pub fn c2_is_active_flag(channel: IpccChannel) -> bool { - let regs = IPCC::regs(); - - unsafe { regs.cpu(1).sr().read().chf(channel as usize) } - } - - pub fn is_tx_pending(channel: IpccChannel) -> bool { - !Self::c1_is_active_flag(channel) && Self::c1_get_tx_channel(channel) - } - - pub fn is_rx_pending(channel: IpccChannel) -> bool { - Self::c2_is_active_flag(channel) && Self::c1_get_rx_channel(channel) - } -} - -impl sealed::Instance for crate::peripherals::IPCC { - fn regs() -> crate::pac::ipcc::Ipcc { - crate::pac::IPCC - } - - fn set_cpu2(enabled: bool) { - unsafe { crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)) } - } -} - -unsafe fn _configure_pwr() { - let rcc = crate::pac::RCC; - - // set RF wake-up clock = LSE - rcc.csr().modify(|w| w.set_rfwkpsel(0b01)); -} diff --git a/embassy-stm32/src/tl_mbox/mm.rs b/embassy-stm32/src/tl_mbox/mm.rs deleted file mode 100644 index a40438499..000000000 --- a/embassy-stm32/src/tl_mbox/mm.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! Memory manager routines - -use core::mem::MaybeUninit; - -use super::evt::EvtPacket; -use super::ipcc::Ipcc; -use super::unsafe_linked_list::LinkedListNode; -use super::{ - channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, - SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, TL_REF_TABLE, -}; - -pub(super) struct MemoryManager; - -impl MemoryManager { - pub fn new() -> Self { - unsafe { - LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); - LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); - - TL_MEM_MANAGER_TABLE = MaybeUninit::new(MemManagerTable { - spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), - spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), - blepool: EVT_POOL.as_ptr().cast(), - blepoolsize: POOL_SIZE as u32, - pevt_free_buffer_queue: FREE_BUF_QUEUE.as_mut_ptr(), - traces_evt_pool: core::ptr::null(), - tracespoolsize: 0, - }); - } - - MemoryManager - } - - pub fn evt_drop(evt: *mut EvtPacket) { - unsafe { - let list_node = evt.cast(); - - LinkedListNode::insert_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); - - let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); - - // postpone event buffer freeing to IPCC interrupt handler - if channel_is_busy { - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); - } else { - Self::send_free_buf(); - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); - } - } - } - - /// gives free event buffers back to CPU2 from local buffer queue - pub fn send_free_buf() { - unsafe { - let mut node_ptr = core::ptr::null_mut(); - let node_ptr_ptr: *mut _ = &mut node_ptr; - - while !LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { - LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), node_ptr_ptr); - LinkedListNode::insert_tail( - (*(*TL_REF_TABLE.as_ptr()).mem_manager_table).pevt_free_buffer_queue, - node_ptr, - ); - } - } - } - - /// free buffer channel interrupt handler - pub fn free_buf_handler() { - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false); - Self::send_free_buf(); - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); - } -} diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32/src/tl_mbox/mod.rs deleted file mode 100644 index 21a954417..000000000 --- a/embassy-stm32/src/tl_mbox/mod.rs +++ /dev/null @@ -1,446 +0,0 @@ -use core::mem::MaybeUninit; - -use bit_field::BitField; -use embassy_cortex_m::interrupt::Interrupt; -use embassy_futures::block_on; -use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; -use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; -use embassy_sync::channel::Channel; -use embassy_sync::signal::Signal; - -use self::cmd::{AclDataPacket, CmdPacket}; -use self::evt::{CcEvt, EvtBox}; -use self::ipcc::{Config, Ipcc}; -use self::unsafe_linked_list::LinkedListNode; -use crate::interrupt; -use crate::peripherals::IPCC; - -pub mod ble; -pub mod channels; -pub mod cmd; -pub mod consts; -pub mod evt; -pub mod hci; -pub mod ipcc; -pub mod mm; -pub mod shci; -pub mod sys; -pub mod unsafe_linked_list; - -/// Interrupt handler. -pub struct ReceiveInterruptHandler {} - -impl interrupt::Handler for ReceiveInterruptHandler { - unsafe fn on_interrupt() { - debug!("ipcc rx interrupt"); - - if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { - debug!("sys evt"); - sys::Sys::evt_handler(); - } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) { - debug!("ble evt"); - ble::Ble::evt_handler(); - } else { - todo!() - } - - STATE.signal(()); - } -} - -pub struct TransmitInterruptHandler {} - -impl interrupt::Handler for TransmitInterruptHandler { - unsafe fn on_interrupt() { - debug!("ipcc tx interrupt"); - - if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { - debug!("sys cmd rsp"); - // TODO: handle this case - let cc = sys::Sys::cmd_evt_handler(); - let a = unsafe { core::slice::from_raw_parts(&cc as *const _ as *const u8, core::mem::size_of::()) }; - debug!("{:#04x}", a); - - LAST_CC_EVT.signal(cc); - } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) { - debug!("mm"); - mm::MemoryManager::free_buf_handler(); - } else { - todo!() - } - - STATE.signal(()); - } -} - -#[derive(Debug, Copy, Clone)] -#[repr(C, packed)] -pub struct SafeBootInfoTable { - version: u32, -} - -#[derive(Debug, Copy, Clone)] -#[repr(C, packed)] -pub struct RssInfoTable { - version: u32, - memory_size: u32, - rss_info: u32, -} - -/** - * Version - * [0:3] = Build - 0: Untracked - 15:Released - x: Tracked version - * [4:7] = branch - 0: Mass Market - x: ... - * [8:15] = Subversion - * [16:23] = Version minor - * [24:31] = Version major - * - * Memory Size - * [0:7] = Flash ( Number of 4k sector) - * [8:15] = Reserved ( Shall be set to 0 - may be used as flash extension ) - * [16:23] = SRAM2b ( Number of 1k sector) - * [24:31] = SRAM2a ( Number of 1k sector) - */ -#[derive(Debug, Copy, Clone)] -#[repr(C, packed)] -pub struct WirelessFwInfoTable { - version: u32, - memory_size: u32, - thread_info: u32, - ble_info: u32, -} - -impl WirelessFwInfoTable { - pub fn version_major(&self) -> u8 { - let version = self.version; - (version.get_bits(24..31) & 0xff) as u8 - } - - pub fn version_minor(&self) -> u8 { - let version = self.version; - (version.clone().get_bits(16..23) & 0xff) as u8 - } - - pub fn subversion(&self) -> u8 { - let version = self.version; - (version.clone().get_bits(8..15) & 0xff) as u8 - } - - /// Size of FLASH, expressed in number of 4K sectors. - pub fn flash_size(&self) -> u8 { - let memory_size = self.memory_size; - (memory_size.clone().get_bits(0..7) & 0xff) as u8 - } - - /// Size of SRAM2a, expressed in number of 1K sectors. - pub fn sram2a_size(&self) -> u8 { - let memory_size = self.memory_size; - (memory_size.clone().get_bits(24..31) & 0xff) as u8 - } - - /// Size of SRAM2b, expressed in number of 1K sectors. - pub fn sram2b_size(&self) -> u8 { - let memory_size = self.memory_size; - (memory_size.clone().get_bits(16..23) & 0xff) as u8 - } -} - -#[derive(Debug, Clone)] -#[repr(C, align(4))] -pub struct DeviceInfoTable { - pub safe_boot_info_table: SafeBootInfoTable, - pub rss_info_table: RssInfoTable, - pub wireless_fw_info_table: WirelessFwInfoTable, -} - -#[derive(Debug)] -#[repr(C, align(4))] -struct BleTable { - pcmd_buffer: *mut CmdPacket, - pcs_buffer: *const u8, - pevt_queue: *const u8, - phci_acl_data_buffer: *mut AclDataPacket, -} - -#[derive(Debug)] -#[repr(C, align(4))] -struct ThreadTable { - nostack_buffer: *const u8, - clicmdrsp_buffer: *const u8, - otcmdrsp_buffer: *const u8, -} - -// TODO: use later -#[derive(Debug)] -#[repr(C, align(4))] -pub struct LldTestsTable { - clicmdrsp_buffer: *const u8, - m0cmd_buffer: *const u8, -} - -// TODO: use later -#[derive(Debug)] -#[repr(C, align(4))] -pub struct BleLldTable { - cmdrsp_buffer: *const u8, - m0cmd_buffer: *const u8, -} - -// TODO: use later -#[derive(Debug)] -#[repr(C, align(4))] -pub struct ZigbeeTable { - notif_m0_to_m4_buffer: *const u8, - appli_cmd_m4_to_m0_bufer: *const u8, - request_m0_to_m4_buffer: *const u8, -} - -#[derive(Debug)] -#[repr(C, align(4))] -struct SysTable { - pcmd_buffer: *mut CmdPacket, - sys_queue: *const LinkedListNode, -} - -#[derive(Debug)] -#[repr(C, align(4))] -struct MemManagerTable { - spare_ble_buffer: *const u8, - spare_sys_buffer: *const u8, - - blepool: *const u8, - blepoolsize: u32, - - pevt_free_buffer_queue: *mut LinkedListNode, - - traces_evt_pool: *const u8, - tracespoolsize: u32, -} - -#[derive(Debug)] -#[repr(C, align(4))] -struct TracesTable { - traces_queue: *const u8, -} - -#[derive(Debug)] -#[repr(C, align(4))] -struct Mac802_15_4Table { - p_cmdrsp_buffer: *const u8, - p_notack_buffer: *const u8, - evt_queue: *const u8, -} - -/// Reference table. Contains pointers to all other tables. -#[derive(Debug, Copy, Clone)] -#[repr(C)] -pub struct RefTable { - device_info_table: *const DeviceInfoTable, - ble_table: *const BleTable, - thread_table: *const ThreadTable, - sys_table: *const SysTable, - mem_manager_table: *const MemManagerTable, - traces_table: *const TracesTable, - mac_802_15_4_table: *const Mac802_15_4Table, -} - -#[link_section = "TL_REF_TABLE"] -pub static mut TL_REF_TABLE: MaybeUninit = MaybeUninit::uninit(); - -#[link_section = "MB_MEM1"] -static mut TL_DEVICE_INFO_TABLE: MaybeUninit = MaybeUninit::uninit(); - -#[link_section = "MB_MEM1"] -static mut TL_BLE_TABLE: MaybeUninit = MaybeUninit::uninit(); - -#[link_section = "MB_MEM1"] -static mut TL_THREAD_TABLE: MaybeUninit = MaybeUninit::uninit(); - -#[link_section = "MB_MEM1"] -static mut TL_SYS_TABLE: MaybeUninit = MaybeUninit::uninit(); - -#[link_section = "MB_MEM1"] -static mut TL_MEM_MANAGER_TABLE: MaybeUninit = MaybeUninit::uninit(); - -#[link_section = "MB_MEM1"] -static mut TL_TRACES_TABLE: MaybeUninit = MaybeUninit::uninit(); - -#[link_section = "MB_MEM1"] -static mut TL_MAC_802_15_4_TABLE: MaybeUninit = MaybeUninit::uninit(); - -#[link_section = "MB_MEM2"] -static mut FREE_BUF_QUEUE: MaybeUninit = MaybeUninit::uninit(); - -// Not in shared RAM -static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit = MaybeUninit::uninit(); - -#[allow(dead_code)] // Not used currently but reserved -#[link_section = "MB_MEM2"] -static mut TRACES_EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); - -type PacketHeader = LinkedListNode; - -const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::(); -const TL_EVT_HEADER_SIZE: usize = 3; -const TL_CS_EVT_SIZE: usize = core::mem::size_of::(); - -#[link_section = "MB_MEM2"] -static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> = - MaybeUninit::uninit(); - -#[link_section = "MB_MEM2"] -static mut EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); - -#[link_section = "MB_MEM2"] -static mut SYSTEM_EVT_QUEUE: MaybeUninit = MaybeUninit::uninit(); - -#[link_section = "MB_MEM2"] -pub static mut SYS_CMD_BUF: MaybeUninit = MaybeUninit::uninit(); - -/** - * Queue length of BLE Event - * This parameter defines the number of asynchronous events that can be stored in the HCI layer before - * being reported to the application. When a command is sent to the BLE core coprocessor, the HCI layer - * is waiting for the event with the Num_HCI_Command_Packets set to 1. The receive queue shall be large - * enough to store all asynchronous events received in between. - * When CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE is set to 27, this allow to store three 255 bytes long asynchronous events - * between the HCI command and its event. - * This parameter depends on the value given to CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE. When the queue size is to small, - * the system may hang if the queue is full with asynchronous events and the HCI layer is still waiting - * for a CC/CS event, In that case, the notification TL_BLE_HCI_ToNot() is called to indicate - * to the application a HCI command did not receive its command event within 30s (Default HCI Timeout). - */ -const CFG_TLBLE_EVT_QUEUE_LENGTH: usize = 5; -const CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255; -const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE; - -const fn divc(x: usize, y: usize) -> usize { - ((x) + (y) - 1) / (y) -} - -const POOL_SIZE: usize = CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); - -#[link_section = "MB_MEM2"] -static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit(); - -#[link_section = "MB_MEM2"] -static mut SYS_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> = - MaybeUninit::uninit(); - -#[link_section = "MB_MEM2"] -static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> = - MaybeUninit::uninit(); - -#[link_section = "MB_MEM2"] -static mut BLE_CMD_BUFFER: MaybeUninit = MaybeUninit::uninit(); - -#[link_section = "MB_MEM2"] -// fuck these "magic" numbers from ST ---v---v -static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); - -static HEAPLESS_EVT_QUEUE: Channel = Channel::new(); - -static STATE: Signal = Signal::new(); - -/// current event that is produced during IPCC IRQ handler execution -/// on SYS channel -/// last received Command Complete event -static LAST_CC_EVT: Signal = Signal::new(); - -pub struct TlMbox<'d> { - sys: sys::Sys, - ble: ble::Ble, - _mm: mm::MemoryManager, - - _ipcc: PeripheralRef<'d, IPCC>, -} - -impl<'d> TlMbox<'d> { - pub fn new( - ipcc: impl Peripheral

+ 'd, - _irqs: impl interrupt::Binding - + interrupt::Binding, - config: Config, - ) -> Self { - into_ref!(ipcc); - - unsafe { - TL_REF_TABLE.as_mut_ptr().write_volatile(RefTable { - device_info_table: TL_DEVICE_INFO_TABLE.as_mut_ptr(), - ble_table: TL_BLE_TABLE.as_ptr(), - thread_table: TL_THREAD_TABLE.as_ptr(), - sys_table: TL_SYS_TABLE.as_ptr(), - mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), - traces_table: TL_TRACES_TABLE.as_ptr(), - mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), - }); - - TL_SYS_TABLE = MaybeUninit::zeroed(); - TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed(); - TL_BLE_TABLE = MaybeUninit::zeroed(); - TL_THREAD_TABLE = MaybeUninit::zeroed(); - TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed(); - TL_TRACES_TABLE = MaybeUninit::zeroed(); - TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed(); - - EVT_POOL = MaybeUninit::zeroed(); - SYS_SPARE_EVT_BUF = MaybeUninit::zeroed(); - BLE_SPARE_EVT_BUF = MaybeUninit::zeroed(); - - CS_BUFFER = MaybeUninit::zeroed(); - BLE_CMD_BUFFER = MaybeUninit::zeroed(); - HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed(); - } - - Ipcc::enable(config); - - let sys = sys::Sys::new(); - let ble = ble::Ble::new(); - let mm = mm::MemoryManager::new(); - - // enable interrupts - crate::interrupt::IPCC_C1_RX::unpend(); - crate::interrupt::IPCC_C1_TX::unpend(); - - unsafe { crate::interrupt::IPCC_C1_RX::enable() }; - unsafe { crate::interrupt::IPCC_C1_TX::enable() }; - - Self { - sys, - ble, - _mm: mm, - _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 - } - } - - /// picks single [`EvtBox`] from internal event queue. - /// - /// Internal event queu is populated in IPCC_RX_IRQ handler - pub fn dequeue_event(&mut self) -> Option { - HEAPLESS_EVT_QUEUE.try_recv().ok() - } - - /// retrieves last Command Complete event and removes it from mailbox - pub fn pop_last_cc_evt(&mut self) -> Option { - if LAST_CC_EVT.signaled() { - let cc = Some(block_on(LAST_CC_EVT.wait())); - LAST_CC_EVT.reset(); - - cc - } else { - None - } - } -} diff --git a/embassy-stm32/src/tl_mbox/shci.rs b/embassy-stm32/src/tl_mbox/shci.rs deleted file mode 100644 index b19baa702..000000000 --- a/embassy-stm32/src/tl_mbox/shci.rs +++ /dev/null @@ -1,100 +0,0 @@ -use super::cmd::CmdPacket; -use super::consts::TlPacketType; -use super::{sys, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE}; - -const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66; - -#[derive(Debug, Clone, Copy)] -#[repr(C, packed)] -pub struct ShciBleInitCmdParam { - /// NOT USED CURRENTLY - pub p_ble_buffer_address: u32, - - /// Size of the Buffer allocated in pBleBufferAddress - pub ble_buffer_size: u32, - - pub num_attr_record: u16, - pub num_attr_serv: u16, - pub attr_value_arr_size: u16, - pub num_of_links: u8, - pub extended_packet_length_enable: u8, - pub pr_write_list_size: u8, - pub mb_lock_count: u8, - - pub att_mtu: u16, - pub slave_sca: u16, - pub master_sca: u8, - pub ls_source: u8, - pub max_conn_event_length: u32, - pub hs_startup_time: u16, - pub viterbi_enable: u8, - pub ll_only: u8, - pub hw_version: u8, -} - -impl Default for ShciBleInitCmdParam { - fn default() -> Self { - Self { - p_ble_buffer_address: 0, - ble_buffer_size: 0, - num_attr_record: 68, - num_attr_serv: 8, - attr_value_arr_size: 1344, - num_of_links: 2, - extended_packet_length_enable: 1, - pr_write_list_size: 0x3A, - mb_lock_count: 0x79, - att_mtu: 156, - slave_sca: 500, - master_sca: 0, - ls_source: 1, - max_conn_event_length: 0xFFFFFFFF, - hs_startup_time: 0x148, - viterbi_enable: 1, - ll_only: 0, - hw_version: 0, - } - } -} - -#[derive(Debug, Clone, Copy, Default)] -#[repr(C, packed)] -pub struct ShciHeader { - metadata: [u32; 3], -} - -#[derive(Debug, Clone, Copy)] -#[repr(C, packed)] -pub struct ShciBleInitCmdPacket { - header: ShciHeader, - param: ShciBleInitCmdParam, -} - -pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE; -#[allow(dead_code)] // Not used currently but reserved -const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; - -pub fn shci_ble_init(param: ShciBleInitCmdParam) { - debug!("shci init"); - - let mut packet = ShciBleInitCmdPacket { - header: ShciHeader::default(), - param, - }; - - let packet_ptr: *mut _ = &mut packet; - - unsafe { - let cmd_ptr: *mut CmdPacket = packet_ptr.cast(); - - (*cmd_ptr).cmdserial.cmd.cmd_code = SCHI_OPCODE_BLE_INIT; - (*cmd_ptr).cmdserial.cmd.payload_len = core::mem::size_of::() as u8; - - let mut p_cmd_buffer = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; - core::ptr::write(p_cmd_buffer, *cmd_ptr); - - p_cmd_buffer.cmdserial.ty = TlPacketType::SysCmd as u8; - - sys::send_cmd(); - } -} diff --git a/embassy-stm32/src/tl_mbox/sys.rs b/embassy-stm32/src/tl_mbox/sys.rs deleted file mode 100644 index c87aa440c..000000000 --- a/embassy-stm32/src/tl_mbox/sys.rs +++ /dev/null @@ -1,76 +0,0 @@ -use embassy_futures::block_on; - -use super::cmd::{CmdPacket, CmdSerial}; -use super::evt::{CcEvt, EvtBox, EvtSerial}; -use super::ipcc::Ipcc; -use super::unsafe_linked_list::LinkedListNode; -use super::{channels, SysTable, HEAPLESS_EVT_QUEUE, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; - -pub struct Sys; - -impl Sys { - pub fn new() -> Self { - unsafe { - LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); - - TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { - pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), - sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), - }) - } - - Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true); - - Sys - } - - pub fn cmd_evt_handler() -> CcEvt { - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, false); - - // ST's command response data structure is really convoluted. - // - // for command response events on SYS channel, the header is missing - // and one should: - // 1. interpret the content of CMD_BUFFER as CmdPacket - // 2. Access CmdPacket's cmdserial field and interpret its content as EvtSerial - // 3. Access EvtSerial's evt field (as Evt) and interpret its payload as CcEvt - // 4. CcEvt type is the actual SHCI response - // 5. profit - unsafe { - let pcmd: *const CmdPacket = (*TL_SYS_TABLE.as_ptr()).pcmd_buffer; - - let a = unsafe { - core::slice::from_raw_parts(&pcmd as *const _ as *const u8, core::mem::size_of::()) - }; - debug!("shci response {:#04x}", a); - - let cmd_serial: *const CmdSerial = &(*pcmd).cmdserial; - let evt_serial: *const EvtSerial = cmd_serial.cast(); - let cc: *const CcEvt = (*evt_serial).evt.payload.as_ptr().cast(); - *cc - } - } - - pub fn evt_handler() { - unsafe { - let mut node_ptr = core::ptr::null_mut(); - let node_ptr_ptr: *mut _ = &mut node_ptr; - - while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { - LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); - - let event = node_ptr.cast(); - let event = EvtBox::new(event); - - block_on(HEAPLESS_EVT_QUEUE.send(event)); - } - } - - Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); - } -} - -pub fn send_cmd() { - Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); - Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); -} diff --git a/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs b/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs deleted file mode 100644 index 482e2bf5a..000000000 --- a/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs +++ /dev/null @@ -1,125 +0,0 @@ -//! Unsafe linked list. -//! Translated from ST's C by `c2rust` tool. - -#![allow( - dead_code, - mutable_transmutes, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_assignments, - unused_mut -)] - -use cortex_m::interrupt; - -#[derive(Copy, Clone)] -#[repr(C, packed(4))] -pub struct LinkedListNode { - pub next: *mut LinkedListNode, - pub prev: *mut LinkedListNode, -} - -impl Default for LinkedListNode { - fn default() -> Self { - LinkedListNode { - next: core::ptr::null_mut(), - prev: core::ptr::null_mut(), - } - } -} - -impl LinkedListNode { - pub unsafe fn init_head(mut list_head: *mut LinkedListNode) { - (*list_head).next = list_head; - (*list_head).prev = list_head; - } - - pub unsafe fn is_empty(mut list_head: *mut LinkedListNode) -> bool { - interrupt::free(|_| ((*list_head).next) == list_head) - } - - pub unsafe fn insert_head(mut list_head: *mut LinkedListNode, mut node: *mut LinkedListNode) { - interrupt::free(|_| { - (*node).next = (*list_head).next; - (*node).prev = list_head; - (*list_head).next = node; - (*(*node).next).prev = node; - }); - } - - pub unsafe fn insert_tail(mut list_head: *mut LinkedListNode, mut node: *mut LinkedListNode) { - interrupt::free(|_| { - (*node).next = list_head; - (*node).prev = (*list_head).prev; - (*list_head).prev = node; - (*(*node).prev).next = node; - }); - } - - pub unsafe fn remove_node(mut node: *mut LinkedListNode) { - interrupt::free(|_| { - (*(*node).prev).next = (*node).next; - (*(*node).next).prev = (*node).prev; - }); - } - - pub unsafe fn remove_head(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { - interrupt::free(|_| { - *node = (*list_head).next; - Self::remove_node((*list_head).next); - }); - } - - pub unsafe fn remove_tail(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { - interrupt::free(|_| { - *node = (*list_head).prev; - Self::remove_node((*list_head).prev); - }); - } - - pub unsafe fn insert_node_after(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) { - interrupt::free(|_| { - (*node).next = (*ref_node).next; - (*node).prev = ref_node; - (*ref_node).next = node; - (*(*node).next).prev = node; - }); - } - - pub unsafe fn insert_node_before(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) { - interrupt::free(|_| { - (*node).next = ref_node; - (*node).prev = (*ref_node).prev; - (*ref_node).prev = node; - (*(*node).prev).next = node; - }); - } - - pub unsafe fn get_size(mut list_head: *mut LinkedListNode) -> usize { - interrupt::free(|_| { - let mut size = 0; - let mut temp: *mut LinkedListNode = core::ptr::null_mut::(); - - temp = (*list_head).next; - while temp != list_head { - size += 1; - temp = (*temp).next - } - - size - }) - } - - pub unsafe fn get_next_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { - interrupt::free(|_| { - *node = (*ref_node).next; - }); - } - - pub unsafe fn get_prev_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { - interrupt::free(|_| { - *node = (*ref_node).prev; - }); - } -} diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs index 0525d3f37..3132ab3e4 100644 --- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs +++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs @@ -4,15 +4,15 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::tl_mbox::hci::RadioCoprocessor; -use embassy_stm32::tl_mbox::ipcc::Config; -use embassy_stm32::tl_mbox::TlMbox; -use embassy_stm32::{bind_interrupts, tl_mbox}; +use embassy_stm32::bind_interrupts; +use embassy_stm32::ipcc::Config; +use embassy_stm32_wpan::rc::RadioCoprocessor; +use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs{ - IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler; - IPCC_C1_TX => tl_mbox::TransmitInterruptHandler; + IPCC_C1_RX => embassy_stm32_wpan::ReceiveInterruptHandler; + IPCC_C1_TX => embassy_stm32_wpan::TransmitInterruptHandler; }); #[embassy_executor::main] @@ -45,16 +45,16 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::new(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config); - let mut rc = RadioCoprocessor::new(mbox, Default::default()); - rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]).unwrap(); + let mut rc = RadioCoprocessor::new(mbox); let response = rc.read().await; info!("coprocessor ready {}", response); + rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]); let response = rc.read().await; - info!("coprocessor ready {}", response); + info!("ble reset rsp {}", response); info!("Test OK"); cortex_m::asm::bkpt(); -- cgit From 2dd5ce83ec0421564e85b667f5dabd592f313e5c Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 12:31:15 +0100 Subject: stm32/ipcc: fix `tl_mbox` example --- examples/stm32wb/src/bin/tl_mbox.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs index 8f4e70af0..ae36a7e79 100644 --- a/examples/stm32wb/src/bin/tl_mbox.rs +++ b/examples/stm32wb/src/bin/tl_mbox.rs @@ -4,14 +4,15 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::tl_mbox::{Config, TlMbox}; -use embassy_stm32::{bind_interrupts, tl_mbox}; +use embassy_stm32::bind_interrupts; +use embassy_stm32::ipcc::Config; +use embassy_stm32_wpan::TlMbox; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs{ - IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler; - IPCC_C1_TX => tl_mbox::TransmitInterruptHandler; + IPCC_C1_RX => embassy_stm32_wpan::ReceiveInterruptHandler; + IPCC_C1_TX => embassy_stm32_wpan::TransmitInterruptHandler; }); #[embassy_executor::main] @@ -44,7 +45,7 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::new(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config); loop { let wireless_fw_info = mbox.wireless_fw_info(); -- cgit From a1b27783a645673500833d13bbabb21d4e4202df Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 14:44:30 +0100 Subject: fix build --- embassy-stm32-wpan/Cargo.toml | 24 ++++++++++++++++++++---- embassy-stm32-wpan/build.rs | 34 ++++++++++++++++++++++++++++++++++ embassy-stm32-wpan/src/lib.rs | 18 +++++++++--------- examples/stm32wb/Cargo.toml | 1 + tests/stm32/src/bin/tl_mbox.rs | 11 ++++++----- 5 files changed, 70 insertions(+), 18 deletions(-) create mode 100644 embassy-stm32-wpan/build.rs diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index a6673d472..058d0e29f 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -5,13 +5,12 @@ edition = "2021" license = "MIT OR Apache-2.0" [dependencies] -embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", features = ["stm32wb55rg"] } +embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]} -embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } -embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } +embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } +embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } cortex-m = "0.7.6" @@ -21,3 +20,20 @@ bit_field = "0.10.2" [features] defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] + +stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] +stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] +stm32wb30ce = [ "embassy-stm32/stm32wb30ce" ] +stm32wb35cc = [ "embassy-stm32/stm32wb35cc" ] +stm32wb35ce = [ "embassy-stm32/stm32wb35ce" ] +stm32wb50cg = [ "embassy-stm32/stm32wb50cg" ] +stm32wb55cc = [ "embassy-stm32/stm32wb55cc" ] +stm32wb55ce = [ "embassy-stm32/stm32wb55ce" ] +stm32wb55cg = [ "embassy-stm32/stm32wb55cg" ] +stm32wb55rc = [ "embassy-stm32/stm32wb55rc" ] +stm32wb55re = [ "embassy-stm32/stm32wb55re" ] +stm32wb55rg = [ "embassy-stm32/stm32wb55rg" ] +stm32wb55vc = [ "embassy-stm32/stm32wb55vc" ] +stm32wb55ve = [ "embassy-stm32/stm32wb55ve" ] +stm32wb55vg = [ "embassy-stm32/stm32wb55vg" ] +stm32wb55vy = [ "embassy-stm32/stm32wb55vy" ] \ No newline at end of file diff --git a/embassy-stm32-wpan/build.rs b/embassy-stm32-wpan/build.rs new file mode 100644 index 000000000..4edf73d59 --- /dev/null +++ b/embassy-stm32-wpan/build.rs @@ -0,0 +1,34 @@ +use std::env; + +fn main() { + match env::vars() + .map(|(a, _)| a) + .filter(|x| x.starts_with("CARGO_FEATURE_STM32")) + .get_one() + { + Ok(_) => {} + Err(GetOneError::None) => panic!("No stm32xx Cargo feature enabled"), + Err(GetOneError::Multiple) => panic!("Multiple stm32xx Cargo features enabled"), + } +} + +enum GetOneError { + None, + Multiple, +} + +trait IteratorExt: Iterator { + fn get_one(self) -> Result; +} + +impl IteratorExt for T { + fn get_one(mut self) -> Result { + match self.next() { + None => Err(GetOneError::None), + Some(res) => match self.next() { + Some(_) => Err(GetOneError::Multiple), + None => Ok(res), + }, + } + } +} diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index b3206428e..c37b67dc4 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -6,10 +6,10 @@ pub mod fmt; use core::mem::MaybeUninit; use cmd::CmdPacket; -use embassy_cortex_m::interrupt::Interrupt; use embassy_futures::block_on; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use embassy_stm32::interrupt; +use embassy_stm32::interrupt::typelevel::Interrupt; use embassy_stm32::ipcc::{Config, Ipcc}; use embassy_stm32::peripherals::IPCC; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; @@ -37,7 +37,7 @@ pub mod unsafe_linked_list; /// Interrupt handler. pub struct ReceiveInterruptHandler {} -impl interrupt::Handler for ReceiveInterruptHandler { +impl interrupt::typelevel::Handler for ReceiveInterruptHandler { unsafe fn on_interrupt() { if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { debug!("RX SYS evt"); @@ -53,7 +53,7 @@ impl interrupt::Handler for ReceiveInterruptHandler { pub struct TransmitInterruptHandler {} -impl interrupt::Handler for TransmitInterruptHandler { +impl interrupt::typelevel::Handler for TransmitInterruptHandler { unsafe fn on_interrupt() { if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { debug!("TX SYS cmd rsp"); @@ -182,8 +182,8 @@ pub struct TlMbox<'d> { impl<'d> TlMbox<'d> { pub fn init( ipcc: impl Peripheral

+ 'd, - _irqs: impl interrupt::Binding - + interrupt::Binding, + _irqs: impl interrupt::typelevel::Binding + + interrupt::typelevel::Binding, config: Config, ) -> Self { into_ref!(ipcc); @@ -223,11 +223,11 @@ impl<'d> TlMbox<'d> { mm::MemoryManager::enable(); // enable interrupts - interrupt::IPCC_C1_RX::unpend(); - interrupt::IPCC_C1_TX::unpend(); + interrupt::typelevel::IPCC_C1_RX::unpend(); + interrupt::typelevel::IPCC_C1_TX::unpend(); - unsafe { interrupt::IPCC_C1_RX::enable() }; - unsafe { interrupt::IPCC_C1_TX::enable() }; + unsafe { interrupt::typelevel::IPCC_C1_RX::enable() }; + unsafe { interrupt::typelevel::IPCC_C1_TX::enable() }; STATE.reset(); diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 14897b171..5b82dd83b 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -9,6 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } +embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs index fab9f0e1b..0f643d578 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/tl_mbox.rs @@ -8,13 +8,14 @@ mod common; use common::*; use embassy_executor::Spawner; -use embassy_stm32::tl_mbox::{Config, TlMbox}; -use embassy_stm32::{bind_interrupts, tl_mbox}; +use embassy_stm32::bind_interrupts; +use embassy_stm32::ipcc::Config; +use embassy_stm32_wpan::TlMbox; use embassy_time::{Duration, Timer}; bind_interrupts!(struct Irqs{ - IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler; - IPCC_C1_TX => tl_mbox::TransmitInterruptHandler; + IPCC_C1_RX => embassy_stm32_wpan::ReceiveInterruptHandler; + IPCC_C1_TX => embassy_stm32_wpan::TransmitInterruptHandler; }); #[embassy_executor::main] @@ -23,7 +24,7 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let config = Config::default(); - let mbox = TlMbox::new(p.IPCC, Irqs, config); + let mbox = TlMbox::init(p.IPCC, Irqs, config); loop { let wireless_fw_info = mbox.wireless_fw_info(); -- cgit From bb5ceb2d9c511e7923b538ac14a30bd78368b189 Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 14:52:14 +0100 Subject: fix CI error --- examples/stm32wb/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 5b82dd83b..83a443754 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } -embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt"] } +embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } defmt = "0.3" defmt-rtt = "0.4" -- cgit From 553c93432559e75d211b84363840f1d272489283 Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 14:54:17 +0100 Subject: fix CI for tests --- tests/stm32/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 3f48bf3f1..3a50493f4 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -29,6 +29,7 @@ embassy-executor = { version = "0.2.0", path = "../../embassy-executor", feature embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } defmt = "0.3.0" defmt-rtt = "0.4" -- cgit From 802416d267028dd0624f6f4183fd1d44278946e1 Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 15:04:52 +0100 Subject: fix CI for tests --- tests/stm32/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 3a50493f4..db97e929b 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -12,7 +12,7 @@ stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo -stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble"] # Nucleo +stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "dep:embassy-stm32-wpan"] # Nucleo stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board @@ -29,7 +29,7 @@ embassy-executor = { version = "0.2.0", path = "../../embassy-executor", feature embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } +embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg"] } defmt = "0.3.0" defmt-rtt = "0.4" -- cgit From bf32dc5d3acee1f73fe445976bde474ffa6d04e0 Mon Sep 17 00:00:00 2001 From: goueslati Date: Mon, 12 Jun 2023 15:07:46 +0100 Subject: clippy --- embassy-stm32-wpan/src/ble.rs | 4 ++-- embassy-stm32-wpan/src/shci.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs index 4546bde07..19955a8a3 100644 --- a/embassy-stm32-wpan/src/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs @@ -63,7 +63,7 @@ impl Ble { core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len()); - let mut cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; + let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; cmd_packet.cmdserial.ty = TlPacketType::BleCmd as u8; } @@ -72,7 +72,7 @@ impl Ble { #[allow(dead_code)] // Not used currently but reserved pub(super) fn ble_send_acl_data() { - let mut cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; + let cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; cmd_packet.acl_data_serial.ty = TlPacketType::AclData as u8; diff --git a/embassy-stm32-wpan/src/shci.rs b/embassy-stm32-wpan/src/shci.rs index 4f4d08886..8537995ff 100644 --- a/embassy-stm32-wpan/src/shci.rs +++ b/embassy-stm32-wpan/src/shci.rs @@ -90,7 +90,7 @@ pub fn shci_ble_init(param: ShciBleInitCmdParam) { (*cmd_ptr).cmdserial.cmd.cmd_code = SCHI_OPCODE_BLE_INIT; (*cmd_ptr).cmdserial.cmd.payload_len = core::mem::size_of::() as u8; - let mut p_cmd_buffer = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; + let p_cmd_buffer = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; core::ptr::write(p_cmd_buffer, *cmd_ptr); p_cmd_buffer.cmdserial.ty = TlPacketType::SysCmd as u8; -- cgit