1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
//! Memory manager routines
use core::future::poll_fn;
use core::mem::MaybeUninit;
use core::task::Poll;
use aligned::{A4, Aligned};
use cortex_m::interrupt;
use embassy_stm32::ipcc::IpccTxChannel;
use embassy_sync::waitqueue::AtomicWaker;
use crate::consts::POOL_SIZE;
use crate::evt;
use crate::evt::EvtPacket;
#[cfg(feature = "ble")]
use crate::tables::BLE_SPARE_EVT_BUF;
use crate::tables::{EVT_POOL, FREE_BUF_QUEUE, MemManagerTable, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE};
use crate::unsafe_linked_list::LinkedListNode;
static MM_WAKER: AtomicWaker = AtomicWaker::new();
static mut LOCAL_FREE_BUF_QUEUE: Aligned<A4, MaybeUninit<LinkedListNode>> = Aligned(MaybeUninit::uninit());
pub struct MemoryManager<'a> {
ipcc_mm_release_buffer_channel: IpccTxChannel<'a>,
}
impl<'a> MemoryManager<'a> {
pub(crate) fn new(ipcc_mm_release_buffer_channel: IpccTxChannel<'a>) -> 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.as_mut_ptr().write_volatile(MemManagerTable {
#[cfg(feature = "ble")]
spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(),
#[cfg(not(feature = "ble"))]
spare_ble_buffer: core::ptr::null(),
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,
});
}
Self {
ipcc_mm_release_buffer_channel,
}
}
pub async fn run_queue(&mut self) -> ! {
loop {
poll_fn(|cx| unsafe {
MM_WAKER.register(cx.waker());
if LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) {
Poll::Pending
} else {
Poll::Ready(())
}
})
.await;
self.ipcc_mm_release_buffer_channel
.send(|| {
interrupt::free(|_| unsafe {
// CS required while moving nodes
while let Some(node_ptr) = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) {
LinkedListNode::insert_head(FREE_BUF_QUEUE.as_mut_ptr(), node_ptr);
}
})
})
.await;
}
}
}
impl<'a> evt::MemoryManager for MemoryManager<'a> {
/// SAFETY: passing a pointer to something other than a managed event packet is UB
unsafe fn drop_event_packet(evt: *mut EvtPacket) {
interrupt::free(|_| unsafe {
LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _);
});
MM_WAKER.wake();
}
}
|