aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32-wpan/src/wb55/sub/mm.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32-wpan/src/wb55/sub/mm.rs')
-rw-r--r--embassy-stm32-wpan/src/wb55/sub/mm.rs86
1 files changed, 86 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..cbb5f130b
--- /dev/null
+++ b/embassy-stm32-wpan/src/wb55/sub/mm.rs
@@ -0,0 +1,86 @@
1//! Memory manager routines
2use core::future::poll_fn;
3use core::mem::MaybeUninit;
4use core::task::Poll;
5
6use aligned::{A4, Aligned};
7use cortex_m::interrupt;
8use embassy_stm32::ipcc::IpccTxChannel;
9use embassy_sync::waitqueue::AtomicWaker;
10
11use crate::consts::POOL_SIZE;
12use crate::evt;
13use crate::evt::EvtPacket;
14#[cfg(feature = "wb55_ble")]
15use crate::tables::BLE_SPARE_EVT_BUF;
16use crate::tables::{EVT_POOL, FREE_BUF_QUEUE, MemManagerTable, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE};
17use crate::unsafe_linked_list::LinkedListNode;
18
19static MM_WAKER: AtomicWaker = AtomicWaker::new();
20static mut LOCAL_FREE_BUF_QUEUE: Aligned<A4, MaybeUninit<LinkedListNode>> = Aligned(MaybeUninit::uninit());
21
22pub struct MemoryManager<'a> {
23 ipcc_mm_release_buffer_channel: IpccTxChannel<'a>,
24}
25
26impl<'a> MemoryManager<'a> {
27 pub(crate) fn new(ipcc_mm_release_buffer_channel: IpccTxChannel<'a>) -> 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 = "wb55_ble")]
34 spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(),
35 #[cfg(not(feature = "wb55_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 {
47 ipcc_mm_release_buffer_channel,
48 }
49 }
50
51 pub async fn run_queue(&mut self) -> ! {
52 loop {
53 poll_fn(|cx| unsafe {
54 MM_WAKER.register(cx.waker());
55 if LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) {
56 Poll::Pending
57 } else {
58 Poll::Ready(())
59 }
60 })
61 .await;
62
63 self.ipcc_mm_release_buffer_channel
64 .send(|| {
65 interrupt::free(|_| unsafe {
66 // CS required while moving nodes
67 while let Some(node_ptr) = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) {
68 LinkedListNode::insert_head(FREE_BUF_QUEUE.as_mut_ptr(), node_ptr);
69 }
70 })
71 })
72 .await;
73 }
74 }
75}
76
77impl<'a> evt::MemoryManager for MemoryManager<'a> {
78 /// SAFETY: passing a pointer to something other than a managed event packet is UB
79 unsafe fn drop_event_packet(evt: *mut EvtPacket) {
80 interrupt::free(|_| unsafe {
81 LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _);
82 });
83
84 MM_WAKER.wake();
85 }
86}