diff options
Diffstat (limited to 'embassy-stm32-wpan/src/sub')
| -rw-r--r-- | embassy-stm32-wpan/src/sub/ble.rs | 124 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/sub/mac.rs | 124 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/sub/mm.rs | 83 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/sub/mod.rs | 6 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/sub/sys.rs | 116 |
5 files changed, 0 insertions, 453 deletions
diff --git a/embassy-stm32-wpan/src/sub/ble.rs b/embassy-stm32-wpan/src/sub/ble.rs deleted file mode 100644 index 0f770d92c..000000000 --- a/embassy-stm32-wpan/src/sub/ble.rs +++ /dev/null | |||
| @@ -1,124 +0,0 @@ | |||
| 1 | use core::ptr; | ||
| 2 | |||
| 3 | use embassy_stm32::ipcc::Ipcc; | ||
| 4 | use hci::Opcode; | ||
| 5 | |||
| 6 | use crate::cmd::CmdPacket; | ||
| 7 | use crate::consts::{TlPacketType, TL_BLEEVT_CC_OPCODE, TL_BLEEVT_CS_OPCODE}; | ||
| 8 | use crate::evt::{EvtBox, EvtPacket, EvtStub}; | ||
| 9 | use crate::sub::mm; | ||
| 10 | use crate::tables::{BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE}; | ||
| 11 | use crate::unsafe_linked_list::LinkedListNode; | ||
| 12 | use crate::{channels, evt}; | ||
| 13 | |||
| 14 | /// A guard that, once constructed, may be used to send BLE commands to CPU2. | ||
| 15 | /// | ||
| 16 | /// It is the responsibility of the caller to ensure that they have awaited an event via | ||
| 17 | /// [crate::sub::sys::Sys::read] before sending any of these commands, and to call | ||
| 18 | /// [crate::sub::sys::Sys::shci_c2_ble_init] and await the HCI_COMMAND_COMPLETE_EVENT before | ||
| 19 | /// sending any other commands. | ||
| 20 | /// | ||
| 21 | /// # Example | ||
| 22 | /// | ||
| 23 | /// ``` | ||
| 24 | /// # embassy_stm32::bind_interrupts!(struct Irqs{ | ||
| 25 | /// # IPCC_C1_RX => ReceiveInterruptHandler; | ||
| 26 | /// # IPCC_C1_TX => TransmitInterruptHandler; | ||
| 27 | /// # }); | ||
| 28 | /// # | ||
| 29 | /// # let p = embassy_stm32::init(embassy_stm32::Config::default()); | ||
| 30 | /// # let mut mbox = embassy_stm32_wpan::TlMbox::init(p.IPCC, Irqs, embassy_stm32::ipcc::Config::default()); | ||
| 31 | /// # | ||
| 32 | /// # let sys_event = mbox.sys_subsystem.read().await; | ||
| 33 | /// # let _command_status = mbox.sys_subsystem.shci_c2_ble_init(Default::default()); | ||
| 34 | /// # // BLE commands may now be sent | ||
| 35 | /// # | ||
| 36 | /// # mbox.ble_subsystem.reset().await; | ||
| 37 | /// # let _reset_response = mbox.ble_subsystem.read().await; | ||
| 38 | /// ``` | ||
| 39 | pub struct Ble { | ||
| 40 | _private: (), | ||
| 41 | } | ||
| 42 | |||
| 43 | impl Ble { | ||
| 44 | /// Constructs a guard that allows for BLE commands to be sent to CPU2. | ||
| 45 | /// | ||
| 46 | /// This takes the place of `TL_BLE_Init`, completing that step as laid out in AN5289, Fig 66. | ||
| 47 | pub(crate) fn new() -> Self { | ||
| 48 | unsafe { | ||
| 49 | LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); | ||
| 50 | |||
| 51 | TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable { | ||
| 52 | pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), | ||
| 53 | pcs_buffer: CS_BUFFER.as_ptr().cast(), | ||
| 54 | pevt_queue: EVT_QUEUE.as_ptr().cast(), | ||
| 55 | phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(), | ||
| 56 | }); | ||
| 57 | } | ||
| 58 | |||
| 59 | Self { _private: () } | ||
| 60 | } | ||
| 61 | |||
| 62 | /// `HW_IPCC_BLE_EvtNot` | ||
| 63 | pub async fn tl_read(&self) -> EvtBox<Self> { | ||
| 64 | Ipcc::receive(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, || unsafe { | ||
| 65 | if let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) { | ||
| 66 | Some(EvtBox::new(node_ptr.cast())) | ||
| 67 | } else { | ||
| 68 | None | ||
| 69 | } | ||
| 70 | }) | ||
| 71 | .await | ||
| 72 | } | ||
| 73 | |||
| 74 | /// `TL_BLE_SendCmd` | ||
| 75 | pub async fn tl_write(&self, opcode: u16, payload: &[u8]) { | ||
| 76 | Ipcc::send(channels::cpu1::IPCC_BLE_CMD_CHANNEL, || unsafe { | ||
| 77 | CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload); | ||
| 78 | }) | ||
| 79 | .await; | ||
| 80 | } | ||
| 81 | |||
| 82 | /// `TL_BLE_SendAclData` | ||
| 83 | pub async fn acl_write(&self, handle: u16, payload: &[u8]) { | ||
| 84 | Ipcc::send(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, || unsafe { | ||
| 85 | CmdPacket::write_into( | ||
| 86 | HCI_ACL_DATA_BUFFER.as_mut_ptr() as *mut _, | ||
| 87 | TlPacketType::AclData, | ||
| 88 | handle, | ||
| 89 | payload, | ||
| 90 | ); | ||
| 91 | }) | ||
| 92 | .await; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | impl evt::MemoryManager for Ble { | ||
| 97 | /// SAFETY: passing a pointer to something other than a managed event packet is UB | ||
| 98 | unsafe fn drop_event_packet(evt: *mut EvtPacket) { | ||
| 99 | let stub = unsafe { | ||
| 100 | let p_evt_stub = &(*evt).evt_serial as *const _ as *const EvtStub; | ||
| 101 | |||
| 102 | ptr::read_volatile(p_evt_stub) | ||
| 103 | }; | ||
| 104 | |||
| 105 | if !(stub.evt_code == TL_BLEEVT_CS_OPCODE || stub.evt_code == TL_BLEEVT_CC_OPCODE) { | ||
| 106 | mm::MemoryManager::drop_event_packet(evt); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | pub extern crate stm32wb_hci as hci; | ||
| 112 | |||
| 113 | impl hci::Controller for Ble { | ||
| 114 | async fn controller_write(&mut self, opcode: Opcode, payload: &[u8]) { | ||
| 115 | self.tl_write(opcode.0, payload).await; | ||
| 116 | } | ||
| 117 | |||
| 118 | async fn controller_read_into(&self, buf: &mut [u8]) { | ||
| 119 | let evt_box = self.tl_read().await; | ||
| 120 | let evt_serial = evt_box.serial(); | ||
| 121 | |||
| 122 | buf[..evt_serial.len()].copy_from_slice(evt_serial); | ||
| 123 | } | ||
| 124 | } | ||
diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs deleted file mode 100644 index baf4da979..000000000 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ /dev/null | |||
| @@ -1,124 +0,0 @@ | |||
| 1 | use core::future::poll_fn; | ||
| 2 | use core::ptr; | ||
| 3 | use core::sync::atomic::{AtomicBool, Ordering}; | ||
| 4 | use core::task::Poll; | ||
| 5 | |||
| 6 | use embassy_futures::poll_once; | ||
| 7 | use embassy_stm32::ipcc::Ipcc; | ||
| 8 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 9 | |||
| 10 | use crate::cmd::CmdPacket; | ||
| 11 | use crate::consts::TlPacketType; | ||
| 12 | use crate::evt::{EvtBox, EvtPacket}; | ||
| 13 | use crate::mac::commands::MacCommand; | ||
| 14 | use crate::mac::event::MacEvent; | ||
| 15 | use crate::mac::typedefs::MacError; | ||
| 16 | use crate::tables::{MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER}; | ||
| 17 | use crate::{channels, evt}; | ||
| 18 | |||
| 19 | static MAC_WAKER: AtomicWaker = AtomicWaker::new(); | ||
| 20 | static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false); | ||
| 21 | |||
| 22 | pub struct Mac { | ||
| 23 | _private: (), | ||
| 24 | } | ||
| 25 | |||
| 26 | impl Mac { | ||
| 27 | pub(crate) fn new() -> Self { | ||
| 28 | Self { _private: () } | ||
| 29 | } | ||
| 30 | |||
| 31 | /// `HW_IPCC_MAC_802_15_4_EvtNot` | ||
| 32 | /// | ||
| 33 | /// This function will stall if the previous `EvtBox` has not been dropped | ||
| 34 | pub async fn tl_read(&self) -> EvtBox<Self> { | ||
| 35 | // Wait for the last event box to be dropped | ||
| 36 | poll_fn(|cx| { | ||
| 37 | MAC_WAKER.register(cx.waker()); | ||
| 38 | if MAC_EVT_OUT.load(Ordering::SeqCst) { | ||
| 39 | Poll::Pending | ||
| 40 | } else { | ||
| 41 | Poll::Ready(()) | ||
| 42 | } | ||
| 43 | }) | ||
| 44 | .await; | ||
| 45 | |||
| 46 | // Return a new event box | ||
| 47 | Ipcc::receive(channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, || unsafe { | ||
| 48 | // The closure is not async, therefore the closure must execute to completion (cannot be dropped) | ||
| 49 | // Therefore, the event box is guaranteed to be cleaned up if it's not leaked | ||
| 50 | MAC_EVT_OUT.store(true, Ordering::SeqCst); | ||
| 51 | |||
| 52 | Some(EvtBox::new(MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _)) | ||
| 53 | }) | ||
| 54 | .await | ||
| 55 | } | ||
| 56 | |||
| 57 | /// `HW_IPCC_MAC_802_15_4_CmdEvtNot` | ||
| 58 | pub async fn tl_write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 { | ||
| 59 | self.tl_write(opcode, payload).await; | ||
| 60 | Ipcc::flush(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL).await; | ||
| 61 | |||
| 62 | unsafe { | ||
| 63 | let p_event_packet = MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket; | ||
| 64 | let p_mac_rsp_evt = &((*p_event_packet).evt_serial.evt.payload) as *const u8; | ||
| 65 | |||
| 66 | ptr::read_volatile(p_mac_rsp_evt) | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | /// `TL_MAC_802_15_4_SendCmd` | ||
| 71 | pub async fn tl_write(&self, opcode: u16, payload: &[u8]) { | ||
| 72 | Ipcc::send(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL, || unsafe { | ||
| 73 | CmdPacket::write_into( | ||
| 74 | MAC_802_15_4_CMD_BUFFER.as_mut_ptr(), | ||
| 75 | TlPacketType::MacCmd, | ||
| 76 | opcode, | ||
| 77 | payload, | ||
| 78 | ); | ||
| 79 | }) | ||
| 80 | .await; | ||
| 81 | } | ||
| 82 | |||
| 83 | pub async fn send_command<T>(&self, cmd: &T) -> Result<(), MacError> | ||
| 84 | where | ||
| 85 | T: MacCommand, | ||
| 86 | { | ||
| 87 | let response = self.tl_write_and_get_response(T::OPCODE as u16, cmd.payload()).await; | ||
| 88 | |||
| 89 | if response == 0x00 { | ||
| 90 | Ok(()) | ||
| 91 | } else { | ||
| 92 | Err(MacError::from(response)) | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | pub async fn read(&self) -> Result<MacEvent<'_>, ()> { | ||
| 97 | MacEvent::new(self.tl_read().await) | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | impl evt::MemoryManager for Mac { | ||
| 102 | /// SAFETY: passing a pointer to something other than a managed event packet is UB | ||
| 103 | unsafe fn drop_event_packet(_: *mut EvtPacket) { | ||
| 104 | trace!("mac drop event"); | ||
| 105 | |||
| 106 | // Write the ack | ||
| 107 | CmdPacket::write_into( | ||
| 108 | MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _, | ||
| 109 | TlPacketType::OtAck, | ||
| 110 | 0, | ||
| 111 | &[], | ||
| 112 | ); | ||
| 113 | |||
| 114 | // Clear the rx flag | ||
| 115 | let _ = poll_once(Ipcc::receive::<()>( | ||
| 116 | channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, | ||
| 117 | || None, | ||
| 118 | )); | ||
| 119 | |||
| 120 | // Allow a new read call | ||
| 121 | MAC_EVT_OUT.store(false, Ordering::SeqCst); | ||
| 122 | MAC_WAKER.wake(); | ||
| 123 | } | ||
| 124 | } | ||
diff --git a/embassy-stm32-wpan/src/sub/mm.rs b/embassy-stm32-wpan/src/sub/mm.rs deleted file mode 100644 index 4e4d2f854..000000000 --- a/embassy-stm32-wpan/src/sub/mm.rs +++ /dev/null | |||
| @@ -1,83 +0,0 @@ | |||
| 1 | //! Memory manager routines | ||
| 2 | use core::future::poll_fn; | ||
| 3 | use core::mem::MaybeUninit; | ||
| 4 | use core::task::Poll; | ||
| 5 | |||
| 6 | use aligned::{Aligned, A4}; | ||
| 7 | use cortex_m::interrupt; | ||
| 8 | use embassy_stm32::ipcc::Ipcc; | ||
| 9 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 10 | |||
| 11 | use crate::consts::POOL_SIZE; | ||
| 12 | use crate::evt::EvtPacket; | ||
| 13 | #[cfg(feature = "ble")] | ||
| 14 | use crate::tables::BLE_SPARE_EVT_BUF; | ||
| 15 | use crate::tables::{MemManagerTable, EVT_POOL, FREE_BUF_QUEUE, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE}; | ||
| 16 | use crate::unsafe_linked_list::LinkedListNode; | ||
| 17 | use crate::{channels, evt}; | ||
| 18 | |||
| 19 | static MM_WAKER: AtomicWaker = AtomicWaker::new(); | ||
| 20 | static mut LOCAL_FREE_BUF_QUEUE: Aligned<A4, MaybeUninit<LinkedListNode>> = Aligned(MaybeUninit::uninit()); | ||
| 21 | |||
| 22 | pub struct MemoryManager { | ||
| 23 | _private: (), | ||
| 24 | } | ||
| 25 | |||
| 26 | impl MemoryManager { | ||
| 27 | pub(crate) fn new() -> Self { | ||
| 28 | unsafe { | ||
| 29 | LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); | ||
| 30 | LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); | ||
| 31 | |||
| 32 | TL_MEM_MANAGER_TABLE.as_mut_ptr().write_volatile(MemManagerTable { | ||
| 33 | #[cfg(feature = "ble")] | ||
| 34 | spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), | ||
| 35 | #[cfg(not(feature = "ble"))] | ||
| 36 | spare_ble_buffer: core::ptr::null(), | ||
| 37 | spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), | ||
| 38 | blepool: EVT_POOL.as_ptr().cast(), | ||
| 39 | blepoolsize: POOL_SIZE as u32, | ||
| 40 | pevt_free_buffer_queue: FREE_BUF_QUEUE.as_mut_ptr(), | ||
| 41 | traces_evt_pool: core::ptr::null(), | ||
| 42 | tracespoolsize: 0, | ||
| 43 | }); | ||
| 44 | } | ||
| 45 | |||
| 46 | Self { _private: () } | ||
| 47 | } | ||
| 48 | |||
| 49 | pub async fn run_queue(&self) { | ||
| 50 | loop { | ||
| 51 | poll_fn(|cx| unsafe { | ||
| 52 | MM_WAKER.register(cx.waker()); | ||
| 53 | if LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { | ||
| 54 | Poll::Pending | ||
| 55 | } else { | ||
| 56 | Poll::Ready(()) | ||
| 57 | } | ||
| 58 | }) | ||
| 59 | .await; | ||
| 60 | |||
| 61 | Ipcc::send(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, || { | ||
| 62 | interrupt::free(|_| unsafe { | ||
| 63 | // CS required while moving nodes | ||
| 64 | while let Some(node_ptr) = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { | ||
| 65 | LinkedListNode::insert_head(FREE_BUF_QUEUE.as_mut_ptr(), node_ptr); | ||
| 66 | } | ||
| 67 | }) | ||
| 68 | }) | ||
| 69 | .await; | ||
| 70 | } | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | impl evt::MemoryManager for MemoryManager { | ||
| 75 | /// SAFETY: passing a pointer to something other than a managed event packet is UB | ||
| 76 | unsafe fn drop_event_packet(evt: *mut EvtPacket) { | ||
| 77 | interrupt::free(|_| unsafe { | ||
| 78 | LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _); | ||
| 79 | }); | ||
| 80 | |||
| 81 | MM_WAKER.wake(); | ||
| 82 | } | ||
| 83 | } | ||
diff --git a/embassy-stm32-wpan/src/sub/mod.rs b/embassy-stm32-wpan/src/sub/mod.rs deleted file mode 100644 index bee3dbdf1..000000000 --- a/embassy-stm32-wpan/src/sub/mod.rs +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #[cfg(feature = "ble")] | ||
| 2 | pub mod ble; | ||
| 3 | #[cfg(feature = "mac")] | ||
| 4 | pub mod mac; | ||
| 5 | pub mod mm; | ||
| 6 | pub mod sys; | ||
diff --git a/embassy-stm32-wpan/src/sub/sys.rs b/embassy-stm32-wpan/src/sub/sys.rs deleted file mode 100644 index cf6df58bf..000000000 --- a/embassy-stm32-wpan/src/sub/sys.rs +++ /dev/null | |||
| @@ -1,116 +0,0 @@ | |||
| 1 | use core::ptr; | ||
| 2 | |||
| 3 | use crate::cmd::CmdPacket; | ||
| 4 | use crate::consts::TlPacketType; | ||
| 5 | use crate::evt::{CcEvt, EvtBox, EvtPacket}; | ||
| 6 | #[allow(unused_imports)] | ||
| 7 | use crate::shci::{SchiCommandStatus, ShciBleInitCmdParam, ShciOpcode}; | ||
| 8 | use crate::sub::mm; | ||
| 9 | use crate::tables::{SysTable, WirelessFwInfoTable}; | ||
| 10 | use crate::unsafe_linked_list::LinkedListNode; | ||
| 11 | use crate::{channels, Ipcc, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE}; | ||
| 12 | |||
| 13 | /// A guard that, once constructed, allows for sys commands to be sent to CPU2. | ||
| 14 | pub struct Sys { | ||
| 15 | _private: (), | ||
| 16 | } | ||
| 17 | |||
| 18 | impl Sys { | ||
| 19 | /// TL_Sys_Init | ||
| 20 | pub(crate) fn new() -> Self { | ||
| 21 | unsafe { | ||
| 22 | LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); | ||
| 23 | |||
| 24 | TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { | ||
| 25 | pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), | ||
| 26 | sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), | ||
| 27 | }); | ||
| 28 | } | ||
| 29 | |||
| 30 | Self { _private: () } | ||
| 31 | } | ||
| 32 | |||
| 33 | /// Returns CPU2 wireless firmware information (if present). | ||
| 34 | pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> { | ||
| 35 | let info = unsafe { TL_DEVICE_INFO_TABLE.as_mut_ptr().read_volatile().wireless_fw_info_table }; | ||
| 36 | |||
| 37 | // Zero version indicates that CPU2 wasn't active and didn't fill the information table | ||
| 38 | if info.version != 0 { | ||
| 39 | Some(info) | ||
| 40 | } else { | ||
| 41 | None | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | pub async fn write(&self, opcode: ShciOpcode, payload: &[u8]) { | ||
| 46 | Ipcc::send(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, || unsafe { | ||
| 47 | CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode as u16, payload); | ||
| 48 | }) | ||
| 49 | .await; | ||
| 50 | } | ||
| 51 | |||
| 52 | /// `HW_IPCC_SYS_CmdEvtNot` | ||
| 53 | pub async fn write_and_get_response(&self, opcode: ShciOpcode, payload: &[u8]) -> Result<SchiCommandStatus, ()> { | ||
| 54 | self.write(opcode, payload).await; | ||
| 55 | Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await; | ||
| 56 | |||
| 57 | unsafe { | ||
| 58 | let p_event_packet = SYS_CMD_BUF.as_ptr() as *const EvtPacket; | ||
| 59 | let p_command_event = &((*p_event_packet).evt_serial.evt.payload) as *const _ as *const CcEvt; | ||
| 60 | let p_payload = &((*p_command_event).payload) as *const u8; | ||
| 61 | |||
| 62 | ptr::read_volatile(p_payload).try_into() | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | #[cfg(feature = "mac")] | ||
| 67 | pub async fn shci_c2_mac_802_15_4_init(&self) -> Result<SchiCommandStatus, ()> { | ||
| 68 | use crate::tables::{ | ||
| 69 | Mac802_15_4Table, TracesTable, MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, | ||
| 70 | TL_MAC_802_15_4_TABLE, TL_TRACES_TABLE, TRACES_EVT_QUEUE, | ||
| 71 | }; | ||
| 72 | |||
| 73 | unsafe { | ||
| 74 | LinkedListNode::init_head(TRACES_EVT_QUEUE.as_mut_ptr() as *mut _); | ||
| 75 | |||
| 76 | TL_TRACES_TABLE.as_mut_ptr().write_volatile(TracesTable { | ||
| 77 | traces_queue: TRACES_EVT_QUEUE.as_ptr() as *const _, | ||
| 78 | }); | ||
| 79 | |||
| 80 | TL_MAC_802_15_4_TABLE.as_mut_ptr().write_volatile(Mac802_15_4Table { | ||
| 81 | p_cmdrsp_buffer: MAC_802_15_4_CMD_BUFFER.as_mut_ptr().cast(), | ||
| 82 | p_notack_buffer: MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr().cast(), | ||
| 83 | evt_queue: core::ptr::null_mut(), | ||
| 84 | }); | ||
| 85 | }; | ||
| 86 | |||
| 87 | self.write_and_get_response(ShciOpcode::Mac802_15_4Init, &[]).await | ||
| 88 | } | ||
| 89 | |||
| 90 | /// Send a request to CPU2 to initialise the BLE stack. | ||
| 91 | /// | ||
| 92 | /// This must be called before any BLE commands are sent via the BLE channel (according to | ||
| 93 | /// AN5289, Figures 65 and 66). It should only be called after CPU2 sends a system event, via | ||
| 94 | /// `HW_IPCC_SYS_EvtNot`, aka `IoBusCallBackUserEvt` (as detailed in Figure 65), aka | ||
| 95 | /// [crate::sub::ble::hci::host::uart::UartHci::read]. | ||
| 96 | #[cfg(feature = "ble")] | ||
| 97 | pub async fn shci_c2_ble_init(&self, param: ShciBleInitCmdParam) -> Result<SchiCommandStatus, ()> { | ||
| 98 | self.write_and_get_response(ShciOpcode::BleInit, param.payload()).await | ||
| 99 | } | ||
| 100 | |||
| 101 | /// `HW_IPCC_SYS_EvtNot` | ||
| 102 | /// | ||
| 103 | /// This method takes the place of the `HW_IPCC_SYS_EvtNot`/`SysUserEvtRx`/`APPE_SysUserEvtRx`, | ||
| 104 | /// as the embassy implementation avoids the need to call C public bindings, and instead | ||
| 105 | /// handles the event channels directly. | ||
| 106 | pub async fn read(&self) -> EvtBox<mm::MemoryManager> { | ||
| 107 | Ipcc::receive(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, || unsafe { | ||
| 108 | if let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) { | ||
| 109 | Some(EvtBox::new(node_ptr.cast())) | ||
| 110 | } else { | ||
| 111 | None | ||
| 112 | } | ||
| 113 | }) | ||
| 114 | .await | ||
| 115 | } | ||
| 116 | } | ||
