aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32-wpan/src/lib.rs
diff options
context:
space:
mode:
authorgoueslati <[email protected]>2023-06-12 12:27:51 +0100
committergoueslati <[email protected]>2023-06-12 12:27:51 +0100
commitca8957da435eb91242fa33eb986e80a33bbc4da0 (patch)
tree89b66bdff52630cd4ef1d609122c2b04417ccd73 /embassy-stm32-wpan/src/lib.rs
parentce1d72c609ae1e04410e68458ec3d6c36c7dae27 (diff)
stm32/ipcc: move tl_mbox into `embassy-stm32-wpan`
Diffstat (limited to 'embassy-stm32-wpan/src/lib.rs')
-rw-r--r--embassy-stm32-wpan/src/lib.rs266
1 files changed, 266 insertions, 0 deletions
diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs
new file mode 100644
index 000000000..b3206428e
--- /dev/null
+++ b/embassy-stm32-wpan/src/lib.rs
@@ -0,0 +1,266 @@
1#![no_std]
2
3// This must go FIRST so that all the other modules see its macros.
4pub mod fmt;
5
6use core::mem::MaybeUninit;
7
8use cmd::CmdPacket;
9use embassy_cortex_m::interrupt::Interrupt;
10use embassy_futures::block_on;
11use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
12use embassy_stm32::interrupt;
13use embassy_stm32::ipcc::{Config, Ipcc};
14use embassy_stm32::peripherals::IPCC;
15use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
16use embassy_sync::channel::Channel;
17use embassy_sync::signal::Signal;
18use evt::{CcEvt, EvtBox};
19use tables::{
20 BleTable, DeviceInfoTable, Mac802_15_4Table, MemManagerTable, RefTable, SysTable, ThreadTable, TracesTable,
21 WirelessFwInfoTable,
22};
23use unsafe_linked_list::LinkedListNode;
24
25pub mod ble;
26pub mod channels;
27pub mod cmd;
28pub mod consts;
29pub mod evt;
30pub mod mm;
31pub mod rc;
32pub mod shci;
33pub mod sys;
34pub mod tables;
35pub mod unsafe_linked_list;
36
37/// Interrupt handler.
38pub struct ReceiveInterruptHandler {}
39
40impl interrupt::Handler<interrupt::IPCC_C1_RX> for ReceiveInterruptHandler {
41 unsafe fn on_interrupt() {
42 if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) {
43 debug!("RX SYS evt");
44 sys::Sys::evt_handler();
45 } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) {
46 debug!("RX BLE evt");
47 ble::Ble::evt_handler();
48 }
49
50 STATE.signal(());
51 }
52}
53
54pub struct TransmitInterruptHandler {}
55
56impl interrupt::Handler<interrupt::IPCC_C1_TX> for TransmitInterruptHandler {
57 unsafe fn on_interrupt() {
58 if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) {
59 debug!("TX SYS cmd rsp");
60 let cc = sys::Sys::cmd_evt_handler();
61
62 LAST_CC_EVT.signal(cc);
63 } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) {
64 debug!("TX MM release");
65 mm::MemoryManager::free_buf_handler();
66 } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL) {
67 debug!("TX HCI acl");
68 ble::Ble::acl_data_handler();
69 }
70
71 STATE.signal(());
72 }
73}
74
75#[link_section = "TL_REF_TABLE"]
76pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit();
77
78#[link_section = "MB_MEM1"]
79static mut TL_DEVICE_INFO_TABLE: MaybeUninit<DeviceInfoTable> = MaybeUninit::uninit();
80
81#[link_section = "MB_MEM1"]
82static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit();
83
84#[link_section = "MB_MEM1"]
85static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit();
86
87#[link_section = "MB_MEM1"]
88static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit();
89
90#[link_section = "MB_MEM1"]
91static mut TL_MEM_MANAGER_TABLE: MaybeUninit<MemManagerTable> = MaybeUninit::uninit();
92
93#[link_section = "MB_MEM1"]
94static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit();
95
96#[link_section = "MB_MEM1"]
97static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit();
98
99#[link_section = "MB_MEM2"]
100static mut FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
101
102// Not in shared RAM
103static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
104
105#[allow(dead_code)] // Not used currently but reserved
106#[link_section = "MB_MEM2"]
107static mut TRACES_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
108
109type PacketHeader = LinkedListNode;
110
111const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::<PacketHeader>();
112const TL_EVT_HEADER_SIZE: usize = 3;
113const TL_CS_EVT_SIZE: usize = core::mem::size_of::<evt::CsEvt>();
114
115#[link_section = "MB_MEM2"]
116static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> =
117 MaybeUninit::uninit();
118
119#[link_section = "MB_MEM2"]
120static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
121
122#[link_section = "MB_MEM2"]
123static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
124
125#[link_section = "MB_MEM2"]
126pub static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
127
128/**
129 * Queue length of BLE Event
130 * This parameter defines the number of asynchronous events that can be stored in the HCI layer before
131 * being reported to the application. When a command is sent to the BLE core coprocessor, the HCI layer
132 * is waiting for the event with the Num_HCI_Command_Packets set to 1. The receive queue shall be large
133 * enough to store all asynchronous events received in between.
134 * When CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE is set to 27, this allow to store three 255 bytes long asynchronous events
135 * between the HCI command and its event.
136 * This parameter depends on the value given to CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE. When the queue size is to small,
137 * the system may hang if the queue is full with asynchronous events and the HCI layer is still waiting
138 * for a CC/CS event, In that case, the notification TL_BLE_HCI_ToNot() is called to indicate
139 * to the application a HCI command did not receive its command event within 30s (Default HCI Timeout).
140 */
141const CFG_TLBLE_EVT_QUEUE_LENGTH: usize = 5;
142const CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255;
143const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE;
144
145const fn divc(x: usize, y: usize) -> usize {
146 ((x) + (y) - 1) / (y)
147}
148
149const POOL_SIZE: usize = CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4);
150
151#[link_section = "MB_MEM2"]
152static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit();
153
154#[link_section = "MB_MEM2"]
155static mut SYS_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
156 MaybeUninit::uninit();
157
158#[link_section = "MB_MEM2"]
159static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
160 MaybeUninit::uninit();
161
162#[link_section = "MB_MEM2"]
163static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
164
165#[link_section = "MB_MEM2"]
166// fuck these "magic" numbers from ST ---v---v
167static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit();
168
169/// current event that is produced during IPCC IRQ handler execution
170/// on SYS channel
171static EVT_CHANNEL: Channel<CriticalSectionRawMutex, EvtBox, 32> = Channel::new();
172
173/// last received Command Complete event
174static LAST_CC_EVT: Signal<CriticalSectionRawMutex, CcEvt> = Signal::new();
175
176static STATE: Signal<CriticalSectionRawMutex, ()> = Signal::new();
177
178pub struct TlMbox<'d> {
179 _ipcc: PeripheralRef<'d, IPCC>,
180}
181
182impl<'d> TlMbox<'d> {
183 pub fn init(
184 ipcc: impl Peripheral<P = IPCC> + 'd,
185 _irqs: impl interrupt::Binding<interrupt::IPCC_C1_RX, ReceiveInterruptHandler>
186 + interrupt::Binding<interrupt::IPCC_C1_TX, TransmitInterruptHandler>,
187 config: Config,
188 ) -> Self {
189 into_ref!(ipcc);
190
191 unsafe {
192 TL_REF_TABLE = MaybeUninit::new(RefTable {
193 device_info_table: TL_DEVICE_INFO_TABLE.as_mut_ptr(),
194 ble_table: TL_BLE_TABLE.as_ptr(),
195 thread_table: TL_THREAD_TABLE.as_ptr(),
196 sys_table: TL_SYS_TABLE.as_ptr(),
197 mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(),
198 traces_table: TL_TRACES_TABLE.as_ptr(),
199 mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(),
200 });
201
202 TL_SYS_TABLE = MaybeUninit::zeroed();
203 TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed();
204 TL_BLE_TABLE = MaybeUninit::zeroed();
205 TL_THREAD_TABLE = MaybeUninit::zeroed();
206 TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed();
207 TL_TRACES_TABLE = MaybeUninit::zeroed();
208 TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed();
209
210 EVT_POOL = MaybeUninit::zeroed();
211 SYS_SPARE_EVT_BUF = MaybeUninit::zeroed();
212 BLE_SPARE_EVT_BUF = MaybeUninit::zeroed();
213
214 CS_BUFFER = MaybeUninit::zeroed();
215 BLE_CMD_BUFFER = MaybeUninit::zeroed();
216 HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed();
217 }
218
219 Ipcc::enable(config);
220
221 sys::Sys::enable();
222 ble::Ble::enable();
223 mm::MemoryManager::enable();
224
225 // enable interrupts
226 interrupt::IPCC_C1_RX::unpend();
227 interrupt::IPCC_C1_TX::unpend();
228
229 unsafe { interrupt::IPCC_C1_RX::enable() };
230 unsafe { interrupt::IPCC_C1_TX::enable() };
231
232 STATE.reset();
233
234 Self { _ipcc: ipcc }
235 }
236
237 /// Returns CPU2 wireless firmware information (if present).
238 pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> {
239 let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table };
240
241 // Zero version indicates that CPU2 wasn't active and didn't fill the information table
242 if info.version != 0 {
243 Some(*info)
244 } else {
245 None
246 }
247 }
248
249 /// picks single [`EvtBox`] from internal event queue.
250 ///
251 /// Internal event queu is populated in IPCC_RX_IRQ handler
252 pub fn dequeue_event(&mut self) -> Option<EvtBox> {
253 EVT_CHANNEL.try_recv().ok()
254 }
255
256 /// retrieves last Command Complete event and removes it from mailbox
257 pub fn pop_last_cc_evt(&mut self) -> Option<CcEvt> {
258 if LAST_CC_EVT.signaled() {
259 let cc = block_on(LAST_CC_EVT.wait());
260 LAST_CC_EVT.reset();
261 Some(cc)
262 } else {
263 None
264 }
265 }
266}