diff options
Diffstat (limited to 'embassy-stm32-wpan/src/wb55/sub/mm.rs')
| -rw-r--r-- | embassy-stm32-wpan/src/wb55/sub/mm.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/embassy-stm32-wpan/src/wb55/sub/mm.rs b/embassy-stm32-wpan/src/wb55/sub/mm.rs new file mode 100644 index 000000000..0ca7d1835 --- /dev/null +++ b/embassy-stm32-wpan/src/wb55/sub/mm.rs | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | //! Memory manager routines | ||
| 2 | use core::future::poll_fn; | ||
| 3 | use core::mem::MaybeUninit; | ||
| 4 | use core::task::Poll; | ||
| 5 | |||
| 6 | use aligned::{A4, Aligned}; | ||
| 7 | use embassy_stm32::ipcc::IpccTxChannel; | ||
| 8 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 9 | |||
| 10 | use crate::consts::POOL_SIZE; | ||
| 11 | use crate::evt; | ||
| 12 | use crate::evt::EvtPacket; | ||
| 13 | #[cfg(feature = "wb55_ble")] | ||
| 14 | use crate::tables::BLE_SPARE_EVT_BUF; | ||
| 15 | use crate::tables::{EVT_POOL, FREE_BUF_QUEUE, MemManagerTable, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE}; | ||
| 16 | use crate::unsafe_linked_list::LinkedListNode; | ||
| 17 | |||
| 18 | static MM_WAKER: AtomicWaker = AtomicWaker::new(); | ||
| 19 | static mut LOCAL_FREE_BUF_QUEUE: Aligned<A4, MaybeUninit<LinkedListNode>> = Aligned(MaybeUninit::uninit()); | ||
| 20 | |||
| 21 | pub struct MemoryManager<'a> { | ||
| 22 | ipcc_mm_release_buffer_channel: IpccTxChannel<'a>, | ||
| 23 | } | ||
| 24 | |||
| 25 | impl<'a> MemoryManager<'a> { | ||
| 26 | pub(crate) fn new(ipcc_mm_release_buffer_channel: IpccTxChannel<'a>) -> Self { | ||
| 27 | unsafe { | ||
| 28 | LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); | ||
| 29 | LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); | ||
| 30 | |||
| 31 | TL_MEM_MANAGER_TABLE.as_mut_ptr().write_volatile(MemManagerTable { | ||
| 32 | #[cfg(feature = "wb55_ble")] | ||
| 33 | spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), | ||
| 34 | #[cfg(not(feature = "wb55_ble"))] | ||
| 35 | spare_ble_buffer: core::ptr::null(), | ||
| 36 | spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), | ||
| 37 | blepool: EVT_POOL.as_ptr().cast(), | ||
| 38 | blepoolsize: POOL_SIZE as u32, | ||
| 39 | pevt_free_buffer_queue: FREE_BUF_QUEUE.as_mut_ptr(), | ||
| 40 | traces_evt_pool: core::ptr::null(), | ||
| 41 | tracespoolsize: 0, | ||
| 42 | }); | ||
| 43 | } | ||
| 44 | |||
| 45 | Self { | ||
| 46 | ipcc_mm_release_buffer_channel, | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | pub async fn run_queue(&mut self) -> ! { | ||
| 51 | loop { | ||
| 52 | poll_fn(|cx| unsafe { | ||
| 53 | MM_WAKER.register(cx.waker()); | ||
| 54 | if critical_section::with(|cs| LinkedListNode::is_empty(cs, LOCAL_FREE_BUF_QUEUE.as_mut_ptr())) { | ||
| 55 | Poll::Pending | ||
| 56 | } else { | ||
| 57 | Poll::Ready(()) | ||
| 58 | } | ||
| 59 | }) | ||
| 60 | .await; | ||
| 61 | |||
| 62 | self.ipcc_mm_release_buffer_channel | ||
| 63 | .send(|| { | ||
| 64 | critical_section::with(|cs| unsafe { | ||
| 65 | while let Some(node_ptr) = LinkedListNode::remove_head(cs, LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { | ||
| 66 | LinkedListNode::insert_head(cs, FREE_BUF_QUEUE.as_mut_ptr(), node_ptr); | ||
| 67 | } | ||
| 68 | }) | ||
| 69 | }) | ||
| 70 | .await; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | impl<'a> evt::MemoryManager for MemoryManager<'a> { | ||
| 76 | /// SAFETY: passing a pointer to something other than a managed event packet is UB | ||
| 77 | unsafe fn drop_event_packet(evt: *mut EvtPacket) { | ||
| 78 | critical_section::with(|cs| unsafe { | ||
| 79 | LinkedListNode::insert_head(cs, LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _); | ||
| 80 | }); | ||
| 81 | |||
| 82 | MM_WAKER.wake(); | ||
| 83 | } | ||
| 84 | } | ||
