diff options
| -rw-r--r-- | embassy-stm32-wpan/src/consts.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/evt.rs | 33 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/sub/ble.rs | 25 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/sub/mac.rs | 48 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/sub/mm.rs | 23 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/sub/sys.rs | 3 | ||||
| -rw-r--r-- | tests/stm32/src/bin/tl_mbox.rs | 4 |
7 files changed, 78 insertions, 62 deletions
diff --git a/embassy-stm32-wpan/src/consts.rs b/embassy-stm32-wpan/src/consts.rs index 9a107306c..f234151d7 100644 --- a/embassy-stm32-wpan/src/consts.rs +++ b/embassy-stm32-wpan/src/consts.rs | |||
| @@ -87,3 +87,7 @@ pub const fn divc(x: usize, y: usize) -> usize { | |||
| 87 | pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE; | 87 | pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE; |
| 88 | #[allow(dead_code)] | 88 | #[allow(dead_code)] |
| 89 | pub const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; | 89 | pub const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; |
| 90 | |||
| 91 | pub const TL_BLEEVT_CC_OPCODE: u8 = 0x0E; | ||
| 92 | pub const TL_BLEEVT_CS_OPCODE: u8 = 0x0F; | ||
| 93 | pub const TL_BLEEVT_VS_OPCODE: u8 = 0xFF; | ||
diff --git a/embassy-stm32-wpan/src/evt.rs b/embassy-stm32-wpan/src/evt.rs index 22f089037..c6528413d 100644 --- a/embassy-stm32-wpan/src/evt.rs +++ b/embassy-stm32-wpan/src/evt.rs | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | use core::marker::PhantomData; | ||
| 1 | use core::{ptr, slice}; | 2 | use core::{ptr, slice}; |
| 2 | 3 | ||
| 3 | use super::PacketHeader; | 4 | use super::PacketHeader; |
| @@ -93,17 +94,22 @@ impl EvtPacket { | |||
| 93 | } | 94 | } |
| 94 | } | 95 | } |
| 95 | 96 | ||
| 97 | pub trait MemoryManager { | ||
| 98 | unsafe fn drop_event_packet(evt: *mut EvtPacket); | ||
| 99 | } | ||
| 100 | |||
| 96 | /// smart pointer to the [`EvtPacket`] that will dispose of [`EvtPacket`] buffer automatically | 101 | /// smart pointer to the [`EvtPacket`] that will dispose of [`EvtPacket`] buffer automatically |
| 97 | /// on [`Drop`] | 102 | /// on [`Drop`] |
| 98 | #[derive(Debug)] | 103 | #[derive(Debug)] |
| 99 | pub struct EvtBox { | 104 | pub struct EvtBox<T: MemoryManager> { |
| 100 | ptr: *mut EvtPacket, | 105 | ptr: *mut EvtPacket, |
| 106 | mm: PhantomData<T>, | ||
| 101 | } | 107 | } |
| 102 | 108 | ||
| 103 | unsafe impl Send for EvtBox {} | 109 | unsafe impl<T: MemoryManager> Send for EvtBox<T> {} |
| 104 | impl EvtBox { | 110 | impl<T: MemoryManager> EvtBox<T> { |
| 105 | pub(super) fn new(ptr: *mut EvtPacket) -> Self { | 111 | pub(super) fn new(ptr: *mut EvtPacket) -> Self { |
| 106 | Self { ptr } | 112 | Self { ptr, mm: PhantomData } |
| 107 | } | 113 | } |
| 108 | 114 | ||
| 109 | /// Returns information about the event | 115 | /// Returns information about the event |
| @@ -126,9 +132,6 @@ impl EvtBox { | |||
| 126 | } | 132 | } |
| 127 | } | 133 | } |
| 128 | 134 | ||
| 129 | /// writes an underlying [`EvtPacket`] into the provided buffer. | ||
| 130 | /// Returns the number of bytes that were written. | ||
| 131 | /// Returns an error if event kind is unknown or if provided buffer size is not enough. | ||
| 132 | pub fn serial<'a>(&'a self) -> &'a [u8] { | 135 | pub fn serial<'a>(&'a self) -> &'a [u8] { |
| 133 | unsafe { | 136 | unsafe { |
| 134 | let evt_serial: *const EvtSerial = &(*self.ptr).evt_serial; | 137 | let evt_serial: *const EvtSerial = &(*self.ptr).evt_serial; |
| @@ -141,20 +144,8 @@ impl EvtBox { | |||
| 141 | } | 144 | } |
| 142 | } | 145 | } |
| 143 | 146 | ||
| 144 | impl Drop for EvtBox { | 147 | impl<T: MemoryManager> Drop for EvtBox<T> { |
| 145 | fn drop(&mut self) { | 148 | fn drop(&mut self) { |
| 146 | #[cfg(feature = "ble")] | 149 | unsafe { T::drop_event_packet(self.ptr) }; |
| 147 | unsafe { | ||
| 148 | use crate::sub::mm; | ||
| 149 | |||
| 150 | mm::MemoryManager::drop_event_packet(self.ptr) | ||
| 151 | }; | ||
| 152 | |||
| 153 | #[cfg(feature = "mac")] | ||
| 154 | unsafe { | ||
| 155 | use crate::sub::mac; | ||
| 156 | |||
| 157 | mac::Mac::drop_event_packet(self.ptr) | ||
| 158 | } | ||
| 159 | } | 150 | } |
| 160 | } | 151 | } |
diff --git a/embassy-stm32-wpan/src/sub/ble.rs b/embassy-stm32-wpan/src/sub/ble.rs index 619cd66a0..cd32692e1 100644 --- a/embassy-stm32-wpan/src/sub/ble.rs +++ b/embassy-stm32-wpan/src/sub/ble.rs | |||
| @@ -1,14 +1,16 @@ | |||
| 1 | use core::marker::PhantomData; | 1 | use core::marker::PhantomData; |
| 2 | use core::ptr; | ||
| 2 | 3 | ||
| 3 | use embassy_stm32::ipcc::Ipcc; | 4 | use embassy_stm32::ipcc::Ipcc; |
| 4 | use hci::Opcode; | 5 | use hci::Opcode; |
| 5 | 6 | ||
| 6 | use crate::channels; | ||
| 7 | use crate::cmd::CmdPacket; | 7 | use crate::cmd::CmdPacket; |
| 8 | use crate::consts::TlPacketType; | 8 | use crate::consts::{TlPacketType, TL_BLEEVT_CC_OPCODE, TL_BLEEVT_CS_OPCODE}; |
| 9 | use crate::evt::EvtBox; | 9 | use crate::evt::{EvtBox, EvtPacket, EvtStub}; |
| 10 | 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::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::unsafe_linked_list::LinkedListNode; |
| 13 | use crate::{channels, evt}; | ||
| 12 | 14 | ||
| 13 | pub struct Ble { | 15 | pub struct Ble { |
| 14 | phantom: PhantomData<Ble>, | 16 | phantom: PhantomData<Ble>, |
| @@ -30,7 +32,7 @@ impl Ble { | |||
| 30 | Self { phantom: PhantomData } | 32 | Self { phantom: PhantomData } |
| 31 | } | 33 | } |
| 32 | /// `HW_IPCC_BLE_EvtNot` | 34 | /// `HW_IPCC_BLE_EvtNot` |
| 33 | pub async fn tl_read(&self) -> EvtBox { | 35 | pub async fn tl_read(&self) -> EvtBox<Self> { |
| 34 | Ipcc::receive(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, || unsafe { | 36 | Ipcc::receive(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, || unsafe { |
| 35 | if let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) { | 37 | if let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) { |
| 36 | Some(EvtBox::new(node_ptr.cast())) | 38 | Some(EvtBox::new(node_ptr.cast())) |
| @@ -63,6 +65,21 @@ impl Ble { | |||
| 63 | } | 65 | } |
| 64 | } | 66 | } |
| 65 | 67 | ||
| 68 | impl evt::MemoryManager for Ble { | ||
| 69 | /// SAFETY: passing a pointer to something other than a managed event packet is UB | ||
| 70 | unsafe fn drop_event_packet(evt: *mut EvtPacket) { | ||
| 71 | let stub = unsafe { | ||
| 72 | let p_evt_stub = &(*evt).evt_serial as *const _ as *const EvtStub; | ||
| 73 | |||
| 74 | ptr::read_volatile(p_evt_stub) | ||
| 75 | }; | ||
| 76 | |||
| 77 | if !(stub.evt_code == TL_BLEEVT_CS_OPCODE || stub.evt_code == TL_BLEEVT_CC_OPCODE) { | ||
| 78 | mm::MemoryManager::drop_event_packet(evt); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 66 | pub extern crate stm32wb_hci as hci; | 83 | pub extern crate stm32wb_hci as hci; |
| 67 | 84 | ||
| 68 | impl hci::Controller for Ble { | 85 | impl hci::Controller for Ble { |
diff --git a/embassy-stm32-wpan/src/sub/mac.rs b/embassy-stm32-wpan/src/sub/mac.rs index d2be1b85c..fd8af8609 100644 --- a/embassy-stm32-wpan/src/sub/mac.rs +++ b/embassy-stm32-wpan/src/sub/mac.rs | |||
| @@ -8,13 +8,13 @@ use embassy_futures::poll_once; | |||
| 8 | use embassy_stm32::ipcc::Ipcc; | 8 | use embassy_stm32::ipcc::Ipcc; |
| 9 | use embassy_sync::waitqueue::AtomicWaker; | 9 | use embassy_sync::waitqueue::AtomicWaker; |
| 10 | 10 | ||
| 11 | use crate::channels; | ||
| 12 | use crate::cmd::CmdPacket; | 11 | use crate::cmd::CmdPacket; |
| 13 | use crate::consts::TlPacketType; | 12 | use crate::consts::TlPacketType; |
| 14 | use crate::evt::{EvtBox, EvtPacket}; | 13 | use crate::evt::{EvtBox, EvtPacket}; |
| 15 | use crate::tables::{ | 14 | use crate::tables::{ |
| 16 | Mac802_15_4Table, MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, TL_MAC_802_15_4_TABLE, | 15 | Mac802_15_4Table, MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, TL_MAC_802_15_4_TABLE, |
| 17 | }; | 16 | }; |
| 17 | use crate::{channels, evt}; | ||
| 18 | 18 | ||
| 19 | static MAC_WAKER: AtomicWaker = AtomicWaker::new(); | 19 | static MAC_WAKER: AtomicWaker = AtomicWaker::new(); |
| 20 | static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false); | 20 | static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false); |
| @@ -36,31 +36,10 @@ impl Mac { | |||
| 36 | Self { phantom: PhantomData } | 36 | Self { phantom: PhantomData } |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | /// SAFETY: passing a pointer to something other than a managed event packet is UB | ||
| 40 | pub(crate) unsafe fn drop_event_packet(_: *mut EvtPacket) { | ||
| 41 | // Write the ack | ||
| 42 | CmdPacket::write_into( | ||
| 43 | MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _, | ||
| 44 | TlPacketType::OtAck, | ||
| 45 | 0, | ||
| 46 | &[], | ||
| 47 | ); | ||
| 48 | |||
| 49 | // Clear the rx flag | ||
| 50 | let _ = poll_once(Ipcc::receive::<bool>( | ||
| 51 | channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, | ||
| 52 | || None, | ||
| 53 | )); | ||
| 54 | |||
| 55 | // Allow a new read call | ||
| 56 | MAC_EVT_OUT.store(false, Ordering::SeqCst); | ||
| 57 | MAC_WAKER.wake(); | ||
| 58 | } | ||
| 59 | |||
| 60 | /// `HW_IPCC_MAC_802_15_4_EvtNot` | 39 | /// `HW_IPCC_MAC_802_15_4_EvtNot` |
| 61 | /// | 40 | /// |
| 62 | /// This function will stall if the previous `EvtBox` has not been dropped | 41 | /// This function will stall if the previous `EvtBox` has not been dropped |
| 63 | pub async fn read(&self) -> EvtBox { | 42 | pub async fn read(&self) -> EvtBox<Self> { |
| 64 | // Wait for the last event box to be dropped | 43 | // Wait for the last event box to be dropped |
| 65 | poll_fn(|cx| { | 44 | poll_fn(|cx| { |
| 66 | MAC_WAKER.register(cx.waker()); | 45 | MAC_WAKER.register(cx.waker()); |
| @@ -109,3 +88,26 @@ impl Mac { | |||
| 109 | .await; | 88 | .await; |
| 110 | } | 89 | } |
| 111 | } | 90 | } |
| 91 | |||
| 92 | impl evt::MemoryManager for Mac { | ||
| 93 | /// SAFETY: passing a pointer to something other than a managed event packet is UB | ||
| 94 | unsafe fn drop_event_packet(_: *mut EvtPacket) { | ||
| 95 | // Write the ack | ||
| 96 | CmdPacket::write_into( | ||
| 97 | MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _, | ||
| 98 | TlPacketType::OtAck, | ||
| 99 | 0, | ||
| 100 | &[], | ||
| 101 | ); | ||
| 102 | |||
| 103 | // Clear the rx flag | ||
| 104 | let _ = poll_once(Ipcc::receive::<bool>( | ||
| 105 | channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, | ||
| 106 | || None, | ||
| 107 | )); | ||
| 108 | |||
| 109 | // Allow a new read call | ||
| 110 | MAC_EVT_OUT.store(false, Ordering::SeqCst); | ||
| 111 | MAC_WAKER.wake(); | ||
| 112 | } | ||
| 113 | } | ||
diff --git a/embassy-stm32-wpan/src/sub/mm.rs b/embassy-stm32-wpan/src/sub/mm.rs index 047fddcd4..1f2ecac2e 100644 --- a/embassy-stm32-wpan/src/sub/mm.rs +++ b/embassy-stm32-wpan/src/sub/mm.rs | |||
| @@ -8,13 +8,13 @@ use cortex_m::interrupt; | |||
| 8 | use embassy_stm32::ipcc::Ipcc; | 8 | use embassy_stm32::ipcc::Ipcc; |
| 9 | use embassy_sync::waitqueue::AtomicWaker; | 9 | use embassy_sync::waitqueue::AtomicWaker; |
| 10 | 10 | ||
| 11 | use crate::channels; | ||
| 12 | use crate::consts::POOL_SIZE; | 11 | use crate::consts::POOL_SIZE; |
| 13 | use crate::evt::EvtPacket; | 12 | use crate::evt::EvtPacket; |
| 14 | use crate::tables::{ | 13 | use crate::tables::{ |
| 15 | MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, | 14 | MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, |
| 16 | }; | 15 | }; |
| 17 | use crate::unsafe_linked_list::LinkedListNode; | 16 | use crate::unsafe_linked_list::LinkedListNode; |
| 17 | use crate::{channels, evt}; | ||
| 18 | 18 | ||
| 19 | static MM_WAKER: AtomicWaker = AtomicWaker::new(); | 19 | static MM_WAKER: AtomicWaker = AtomicWaker::new(); |
| 20 | static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | 20 | static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); |
| @@ -43,16 +43,6 @@ impl MemoryManager { | |||
| 43 | Self { phantom: PhantomData } | 43 | Self { phantom: PhantomData } |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | #[allow(dead_code)] | ||
| 47 | /// SAFETY: passing a pointer to something other than a managed event packet is UB | ||
| 48 | pub(crate) unsafe fn drop_event_packet(evt: *mut EvtPacket) { | ||
| 49 | interrupt::free(|_| unsafe { | ||
| 50 | LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _); | ||
| 51 | }); | ||
| 52 | |||
| 53 | MM_WAKER.wake(); | ||
| 54 | } | ||
| 55 | |||
| 56 | pub async fn run_queue(&self) { | 46 | pub async fn run_queue(&self) { |
| 57 | loop { | 47 | loop { |
| 58 | poll_fn(|cx| unsafe { | 48 | poll_fn(|cx| unsafe { |
| @@ -77,3 +67,14 @@ impl MemoryManager { | |||
| 77 | } | 67 | } |
| 78 | } | 68 | } |
| 79 | } | 69 | } |
| 70 | |||
| 71 | impl evt::MemoryManager for MemoryManager { | ||
| 72 | /// SAFETY: passing a pointer to something other than a managed event packet is UB | ||
| 73 | unsafe fn drop_event_packet(evt: *mut EvtPacket) { | ||
| 74 | interrupt::free(|_| unsafe { | ||
| 75 | LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _); | ||
| 76 | }); | ||
| 77 | |||
| 78 | MM_WAKER.wake(); | ||
| 79 | } | ||
| 80 | } | ||
diff --git a/embassy-stm32-wpan/src/sub/sys.rs b/embassy-stm32-wpan/src/sub/sys.rs index 2b699b725..af652860d 100644 --- a/embassy-stm32-wpan/src/sub/sys.rs +++ b/embassy-stm32-wpan/src/sub/sys.rs | |||
| @@ -6,6 +6,7 @@ use crate::consts::TlPacketType; | |||
| 6 | use crate::evt::{CcEvt, EvtBox, EvtPacket}; | 6 | use crate::evt::{CcEvt, EvtBox, EvtPacket}; |
| 7 | #[allow(unused_imports)] | 7 | #[allow(unused_imports)] |
| 8 | use crate::shci::{SchiCommandStatus, ShciBleInitCmdParam, ShciOpcode}; | 8 | use crate::shci::{SchiCommandStatus, ShciBleInitCmdParam, ShciOpcode}; |
| 9 | use crate::sub::mm; | ||
| 9 | use crate::tables::{SysTable, WirelessFwInfoTable}; | 10 | use crate::tables::{SysTable, WirelessFwInfoTable}; |
| 10 | use crate::unsafe_linked_list::LinkedListNode; | 11 | 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 | use crate::{channels, Ipcc, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE}; |
| @@ -73,7 +74,7 @@ impl Sys { | |||
| 73 | } | 74 | } |
| 74 | 75 | ||
| 75 | /// `HW_IPCC_SYS_EvtNot` | 76 | /// `HW_IPCC_SYS_EvtNot` |
| 76 | pub async fn read(&self) -> EvtBox { | 77 | pub async fn read(&self) -> EvtBox<mm::MemoryManager> { |
| 77 | Ipcc::receive(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, || unsafe { | 78 | Ipcc::receive(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, || unsafe { |
| 78 | if let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) { | 79 | if let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) { |
| 79 | Some(EvtBox::new(node_ptr.cast())) | 80 | Some(EvtBox::new(node_ptr.cast())) |
diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs index 8880554de..af3832709 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/tl_mbox.rs | |||
| @@ -39,14 +39,14 @@ async fn run_mm_queue(memory_manager: mm::MemoryManager) { | |||
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | #[embassy_executor::main] | 41 | #[embassy_executor::main] |
| 42 | async fn main(_spawner: Spawner) { | 42 | async fn main(spawner: Spawner) { |
| 43 | let p = embassy_stm32::init(config()); | 43 | let p = embassy_stm32::init(config()); |
| 44 | info!("Hello World!"); | 44 | info!("Hello World!"); |
| 45 | 45 | ||
| 46 | let config = Config::default(); | 46 | let config = Config::default(); |
| 47 | let mut mbox = TlMbox::init(p.IPCC, Irqs, config); | 47 | let mut mbox = TlMbox::init(p.IPCC, Irqs, config); |
| 48 | 48 | ||
| 49 | // spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); | 49 | spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); |
| 50 | 50 | ||
| 51 | let sys_event = mbox.sys_subsystem.read().await; | 51 | let sys_event = mbox.sys_subsystem.read().await; |
| 52 | info!("sys event: {}", sys_event.payload()); | 52 | info!("sys event: {}", sys_event.payload()); |
