aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32-wpan/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32-wpan/src/lib.rs')
-rw-r--r--embassy-stm32-wpan/src/lib.rs199
1 files changed, 2 insertions, 197 deletions
diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs
index 18b0feada..bd58a0ca7 100644
--- a/embassy-stm32-wpan/src/lib.rs
+++ b/embassy-stm32-wpan/src/lib.rs
@@ -18,201 +18,6 @@
18// #![warn(missing_docs)] 18// #![warn(missing_docs)]
19#![allow(static_mut_refs)] // TODO: Fix 19#![allow(static_mut_refs)] // TODO: Fix
20 20
21// This must go FIRST so that all the other modules see its macros. 21mod wb55;
22mod fmt;
23 22
24use core::mem::MaybeUninit; 23pub use wb55::*;
25use core::sync::atomic::{Ordering, compiler_fence};
26
27use embassy_hal_internal::Peri;
28use embassy_stm32::interrupt;
29use embassy_stm32::ipcc::{Config, Ipcc, IpccRxChannel, ReceiveInterruptHandler, TransmitInterruptHandler};
30use embassy_stm32::peripherals::IPCC;
31use sub::mm::MemoryManager;
32use sub::sys::Sys;
33use tables::*;
34use unsafe_linked_list::LinkedListNode;
35
36pub mod channels;
37pub mod cmd;
38pub mod consts;
39pub mod evt;
40pub mod lhci;
41pub mod shci;
42pub mod sub;
43pub mod tables;
44pub mod unsafe_linked_list;
45
46#[cfg(feature = "mac")]
47pub mod mac;
48
49#[cfg(feature = "ble")]
50pub use crate::sub::ble::hci;
51
52type PacketHeader = LinkedListNode;
53
54/// Transport Layer for the Mailbox interface
55pub struct TlMbox<'d> {
56 pub sys_subsystem: Sys<'d>,
57 pub mm_subsystem: MemoryManager<'d>,
58 #[cfg(feature = "ble")]
59 pub ble_subsystem: sub::ble::Ble<'d>,
60 #[cfg(feature = "mac")]
61 pub mac_subsystem: sub::mac::Mac<'d>,
62 pub traces: IpccRxChannel<'d>,
63}
64
65impl<'d> TlMbox<'d> {
66 /// Initialise the Transport Layer, and creates and returns a wrapper around it.
67 ///
68 /// This method performs the initialisation laid out in AN5289 annex 14.1. However, it differs
69 /// from the implementation documented in Figure 64, to avoid needing to reference any C
70 /// function pointers.
71 ///
72 /// Annex 14.1 lays out the following methods that should be called:
73 /// 1. tl_mbox.c/TL_Init, which initialises the reference table that is shared between CPU1
74 /// and CPU2.
75 /// 2. shci_tl.c/shci_init(), which initialises the system transport layer, and in turn
76 /// calls tl_mbox.c/TL_SYS_Init, which initialises SYSTEM_EVT_QUEUE channel.
77 /// 3. tl_mbox.c/TL_MM_Init(), which initialises the channel used for sending memory
78 /// manager commands.
79 /// 4. tl_mbox.c/TL_Enable(), which enables the IPCC, and starts CPU2.
80 /// This implementation initialises all of the shared refernce tables and all IPCC channel that
81 /// would be initialised by this process. The developer should therefore treat this method as
82 /// completing all steps in Figure 64.
83 ///
84 /// Once this method has been called, no system commands may be sent until the CPU2 ready
85 /// signal is received, via [sys_subsystem.read]; this completes the procedure laid out in
86 /// Figure 65.
87 ///
88 /// If the `ble` feature is enabled, at this point, the user should call
89 /// [sys_subsystem.shci_c2_ble_init], before any commands are written to the
90 /// [TlMbox.ble_subsystem] ([sub::ble::Ble::new()] completes the process that would otherwise
91 /// be handled by `TL_BLE_Init`; see Figure 66). This completes the procedure laid out in
92 /// Figure 66.
93 // TODO: document what the user should do after calling init to use the mac_802_15_4 subsystem
94 pub async fn init(
95 ipcc: Peri<'d, IPCC>,
96 _irqs: impl interrupt::typelevel::Binding<interrupt::typelevel::IPCC_C1_RX, ReceiveInterruptHandler>
97 + interrupt::typelevel::Binding<interrupt::typelevel::IPCC_C1_TX, TransmitInterruptHandler>,
98 config: Config,
99 ) -> Self {
100 // this is an inlined version of TL_Init from the STM32WB firmware as requested by AN5289.
101 // HW_IPCC_Init is not called, and its purpose is (presumably?) covered by this
102 // implementation
103 unsafe {
104 TL_REF_TABLE.as_mut_ptr().write_volatile(RefTable {
105 device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(),
106 ble_table: TL_BLE_TABLE.as_ptr(),
107 thread_table: TL_THREAD_TABLE.as_ptr(),
108 sys_table: TL_SYS_TABLE.as_ptr(),
109 mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(),
110 traces_table: TL_TRACES_TABLE.as_ptr(),
111 mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(),
112 zigbee_table: TL_ZIGBEE_TABLE.as_ptr(),
113 lld_tests_table: TL_LLD_TESTS_TABLE.as_ptr(),
114 ble_lld_table: TL_BLE_LLD_TABLE.as_ptr(),
115 });
116
117 TL_SYS_TABLE
118 .as_mut_ptr()
119 .write_volatile(MaybeUninit::zeroed().assume_init());
120 TL_DEVICE_INFO_TABLE
121 .as_mut_ptr()
122 .write_volatile(MaybeUninit::zeroed().assume_init());
123 TL_BLE_TABLE
124 .as_mut_ptr()
125 .write_volatile(MaybeUninit::zeroed().assume_init());
126 TL_THREAD_TABLE
127 .as_mut_ptr()
128 .write_volatile(MaybeUninit::zeroed().assume_init());
129 TL_MEM_MANAGER_TABLE
130 .as_mut_ptr()
131 .write_volatile(MaybeUninit::zeroed().assume_init());
132
133 TL_TRACES_TABLE
134 .as_mut_ptr()
135 .write_volatile(MaybeUninit::zeroed().assume_init());
136 TL_MAC_802_15_4_TABLE
137 .as_mut_ptr()
138 .write_volatile(MaybeUninit::zeroed().assume_init());
139 TL_ZIGBEE_TABLE
140 .as_mut_ptr()
141 .write_volatile(MaybeUninit::zeroed().assume_init());
142 TL_LLD_TESTS_TABLE
143 .as_mut_ptr()
144 .write_volatile(MaybeUninit::zeroed().assume_init());
145 TL_BLE_LLD_TABLE
146 .as_mut_ptr()
147 .write_volatile(MaybeUninit::zeroed().assume_init());
148
149 EVT_POOL
150 .as_mut_ptr()
151 .write_volatile(MaybeUninit::zeroed().assume_init());
152 SYS_SPARE_EVT_BUF
153 .as_mut_ptr()
154 .write_volatile(MaybeUninit::zeroed().assume_init());
155 CS_BUFFER
156 .as_mut_ptr()
157 .write_volatile(MaybeUninit::zeroed().assume_init());
158
159 #[cfg(feature = "ble")]
160 {
161 BLE_SPARE_EVT_BUF
162 .as_mut_ptr()
163 .write_volatile(MaybeUninit::zeroed().assume_init());
164
165 BLE_CMD_BUFFER
166 .as_mut_ptr()
167 .write_volatile(MaybeUninit::zeroed().assume_init());
168 HCI_ACL_DATA_BUFFER
169 .as_mut_ptr()
170 .write_volatile(MaybeUninit::zeroed().assume_init());
171 }
172
173 #[cfg(feature = "mac")]
174 {
175 MAC_802_15_4_CMD_BUFFER
176 .as_mut_ptr()
177 .write_volatile(MaybeUninit::zeroed().assume_init());
178 MAC_802_15_4_NOTIF_RSP_EVT_BUFFER
179 .as_mut_ptr()
180 .write_volatile(MaybeUninit::zeroed().assume_init());
181 }
182 }
183
184 compiler_fence(Ordering::SeqCst);
185
186 // this is equivalent to `HW_IPCC_Enable`, which is called by `TL_Enable`
187 let [
188 (_hw_ipcc_ble_cmd_channel, _ipcc_ble_event_channel),
189 (ipcc_system_cmd_rsp_channel, ipcc_system_event_channel),
190 (_ipcc_mac_802_15_4_cmd_rsp_channel, _ipcc_mac_802_15_4_notification_ack_channel),
191 (ipcc_mm_release_buffer_channel, _ipcc_traces_channel),
192 (_ipcc_ble_lld_cmd_channel, _ipcc_ble_lld_rsp_channel),
193 (_ipcc_hci_acl_data_channel, _),
194 ] = Ipcc::new(ipcc, _irqs, config).split();
195
196 let mm = sub::mm::MemoryManager::new(ipcc_mm_release_buffer_channel);
197 let mut sys = sub::sys::Sys::new(ipcc_system_cmd_rsp_channel, ipcc_system_event_channel);
198
199 debug!("sys event: {}", sys.read().await.payload());
200
201 Self {
202 sys_subsystem: sys,
203 #[cfg(feature = "ble")]
204 ble_subsystem: sub::ble::Ble::new(
205 _hw_ipcc_ble_cmd_channel,
206 _ipcc_ble_event_channel,
207 _ipcc_hci_acl_data_channel,
208 ),
209 #[cfg(feature = "mac")]
210 mac_subsystem: sub::mac::Mac::new(
211 _ipcc_mac_802_15_4_cmd_rsp_channel,
212 _ipcc_mac_802_15_4_notification_ack_channel,
213 ),
214 mm_subsystem: mm,
215 traces: _ipcc_traces_channel,
216 }
217 }
218}