aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32/src')
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/tl_mbox/ble.rs26
-rw-r--r--embassy-stm32/src/tl_mbox/channels.rs104
-rw-r--r--embassy-stm32/src/tl_mbox/cmd.rs49
-rw-r--r--embassy-stm32/src/tl_mbox/evt.rs8
-rw-r--r--embassy-stm32/src/tl_mbox/mm.rs30
-rw-r--r--embassy-stm32/src/tl_mbox/mod.rs318
-rw-r--r--embassy-stm32/src/tl_mbox/sys.rs24
-rw-r--r--embassy-stm32/src/tl_mbox/unsafe_linked_list.rs123
9 files changed, 684 insertions, 0 deletions
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 11820b7a0..b3dbe1e2f 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -57,6 +57,8 @@ pub mod rtc;
57pub mod sdmmc; 57pub mod sdmmc;
58#[cfg(spi)] 58#[cfg(spi)]
59pub mod spi; 59pub mod spi;
60#[cfg(stm32wb)]
61pub mod tl_mbox;
60#[cfg(usart)] 62#[cfg(usart)]
61pub mod usart; 63pub mod usart;
62#[cfg(all(usb, feature = "time"))] 64#[cfg(all(usb, feature = "time"))]
diff --git a/embassy-stm32/src/tl_mbox/ble.rs b/embassy-stm32/src/tl_mbox/ble.rs
new file mode 100644
index 000000000..a2c0758d1
--- /dev/null
+++ b/embassy-stm32/src/tl_mbox/ble.rs
@@ -0,0 +1,26 @@
1use core::mem::MaybeUninit;
2
3use super::unsafe_linked_list::LST_init_head;
4use super::{channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE};
5use crate::ipcc::Ipcc;
6
7pub struct Ble;
8
9impl Ble {
10 pub fn new(ipcc: &mut Ipcc) -> Self {
11 unsafe {
12 LST_init_head(EVT_QUEUE.as_mut_ptr());
13
14 TL_BLE_TABLE = MaybeUninit::new(BleTable {
15 pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(),
16 pcs_buffer: CS_BUFFER.as_mut_ptr().cast(),
17 pevt_queue: EVT_QUEUE.as_ptr().cast(),
18 phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(),
19 });
20 }
21
22 ipcc.c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true);
23
24 Ble
25 }
26}
diff --git a/embassy-stm32/src/tl_mbox/channels.rs b/embassy-stm32/src/tl_mbox/channels.rs
new file mode 100644
index 000000000..1dde5d61c
--- /dev/null
+++ b/embassy-stm32/src/tl_mbox/channels.rs
@@ -0,0 +1,104 @@
1//! CPU1 CPU2
2//! | (SYSTEM) |
3//! |----HW_IPCC_SYSTEM_CMD_RSP_CHANNEL-------------->|
4//! | |
5//! |<---HW_IPCC_SYSTEM_EVENT_CHANNEL-----------------|
6//! | |
7//! | (ZIGBEE) |
8//! |----HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL------------>|
9//! | |
10//! |----HW_IPCC_ZIGBEE_CMD_CLI_CHANNEL-------------->|
11//! | |
12//! |<---HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL-------|
13//! | |
14//! |<---HW_IPCC_ZIGBEE_CLI_NOTIF_ACK_CHANNEL---------|
15//! | |
16//! | (THREAD) |
17//! |----HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL----------->|
18//! | |
19//! |----HW_IPCC_THREAD_CLI_CMD_CHANNEL-------------->|
20//! | |
21//! |<---HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL------|
22//! | |
23//! |<---HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL--|
24//! | |
25//! | (BLE) |
26//! |----HW_IPCC_BLE_CMD_CHANNEL--------------------->|
27//! | |
28//! |----HW_IPCC_HCI_ACL_DATA_CHANNEL---------------->|
29//! | |
30//! |<---HW_IPCC_BLE_EVENT_CHANNEL--------------------|
31//! | |
32//! | (BLE LLD) |
33//! |----HW_IPCC_BLE_LLD_CMD_CHANNEL----------------->|
34//! | |
35//! |<---HW_IPCC_BLE_LLD_RSP_CHANNEL------------------|
36//! | |
37//! |<---HW_IPCC_BLE_LLD_M0_CMD_CHANNEL---------------|
38//! | |
39//! | (MAC) |
40//! |----HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL-------->|
41//! | |
42//! |<---HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL|
43//! | |
44//! | (BUFFER) |
45//! |----HW_IPCC_MM_RELEASE_BUFFER_CHANNE------------>|
46//! | |
47//! | (TRACE) |
48//! |<----HW_IPCC_TRACES_CHANNEL----------------------|
49//! | |
50//!
51
52pub mod cpu1 {
53 use crate::ipcc::IpccChannel;
54
55 #[allow(dead_code)] // Not used currently but reserved
56 pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1;
57 #[allow(dead_code)] // Not used currently but reserved
58 pub const IPCC_SYSTEM_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel2;
59 #[allow(dead_code)] // Not used currently but reserved
60 pub const IPCC_THREAD_OT_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3;
61 #[allow(dead_code)] // Not used currently but reserved
62 pub const IPCC_ZIGBEE_CMD_APPLI_CHANNEL: IpccChannel = IpccChannel::Channel3;
63 #[allow(dead_code)] // Not used currently but reserved
64 pub const IPCC_MAC_802_15_4_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3;
65 #[allow(dead_code)] // Not used currently but reserved
66 pub const IPCC_MM_RELEASE_BUFFER_CHANNEL: IpccChannel = IpccChannel::Channel4;
67 #[allow(dead_code)] // Not used currently but reserved
68 pub const IPCC_THREAD_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5;
69 #[allow(dead_code)] // Not used currently but reserved
70 pub const IPCC_LLDTESTS_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5;
71 #[allow(dead_code)] // Not used currently but reserved
72 pub const IPCC_BLE_LLD_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5;
73 #[allow(dead_code)] // Not used currently but reserved
74 pub const IPCC_HCI_ACL_DATA_CHANNEL: IpccChannel = IpccChannel::Channel6;
75}
76
77pub mod cpu2 {
78 use crate::ipcc::IpccChannel;
79
80 pub const IPCC_BLE_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel1;
81 pub const IPCC_SYSTEM_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel2;
82 #[allow(dead_code)] // Not used currently but reserved
83 pub const IPCC_THREAD_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3;
84 #[allow(dead_code)] // Not used currently but reserved
85 pub const IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3;
86 #[allow(dead_code)] // Not used currently but reserved
87 pub const IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3;
88 #[allow(dead_code)] // Not used currently but reserved
89 pub const IPCC_LDDTESTS_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3;
90 #[allow(dead_code)] // Not used currently but reserved
91 pub const IPCC_BLE_LLDÇM0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3;
92 #[allow(dead_code)] // Not used currently but reserved
93 pub const IPCC_TRACES_CHANNEL: IpccChannel = IpccChannel::Channel4;
94 #[allow(dead_code)] // Not used currently but reserved
95 pub const IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel5;
96 #[allow(dead_code)] // Not used currently but reserved
97 pub const IPCC_LLDTESTS_CLI_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5;
98 #[allow(dead_code)] // Not used currently but reserved
99 pub const IPCC_BLE_LLD_CLI_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5;
100 #[allow(dead_code)] // Not used currently but reserved
101 pub const IPCC_BLE_LLD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5;
102 #[allow(dead_code)] // Not used currently but reserved
103 pub const IPCC_ZIGBEE_M0_REQUEST_CHANNEL: IpccChannel = IpccChannel::Channel5;
104}
diff --git a/embassy-stm32/src/tl_mbox/cmd.rs b/embassy-stm32/src/tl_mbox/cmd.rs
new file mode 100644
index 000000000..3507c3231
--- /dev/null
+++ b/embassy-stm32/src/tl_mbox/cmd.rs
@@ -0,0 +1,49 @@
1use super::PacketHeader;
2
3#[repr(C, packed)]
4#[derive(Copy, Clone)]
5pub struct Cmd {
6 pub cmd_code: u16,
7 pub payload_len: u8,
8 pub payload: [u8; 255],
9}
10
11impl Default for Cmd {
12 fn default() -> Self {
13 Self {
14 cmd_code: 0,
15 payload_len: 0,
16 payload: [0u8; 255],
17 }
18 }
19}
20
21#[repr(C, packed)]
22#[derive(Copy, Clone, Default)]
23pub struct CmdSerial {
24 pub ty: u8,
25 pub cmd: Cmd,
26}
27
28#[repr(C, packed)]
29#[derive(Copy, Clone, Default)]
30pub struct CmdPacket {
31 pub header: PacketHeader,
32 pub cmd_serial: CmdSerial,
33}
34
35#[repr(C, packed)]
36#[derive(Copy, Clone)]
37pub struct AclDataSerial {
38 pub ty: u8,
39 pub handle: u16,
40 pub length: u16,
41 pub acl_data: [u8; 1],
42}
43
44#[repr(C, packed)]
45#[derive(Copy, Clone)]
46pub struct AclDataPacket {
47 pub header: PacketHeader,
48 pub acl_data_serial: AclDataSerial,
49}
diff --git a/embassy-stm32/src/tl_mbox/evt.rs b/embassy-stm32/src/tl_mbox/evt.rs
new file mode 100644
index 000000000..4244db810
--- /dev/null
+++ b/embassy-stm32/src/tl_mbox/evt.rs
@@ -0,0 +1,8 @@
1/// the payload of [`Evt`] for a command status event
2#[derive(Copy, Clone)]
3#[repr(C, packed)]
4pub struct CsEvt {
5 pub status: u8,
6 pub num_cmd: u8,
7 pub cmd_code: u16,
8}
diff --git a/embassy-stm32/src/tl_mbox/mm.rs b/embassy-stm32/src/tl_mbox/mm.rs
new file mode 100644
index 000000000..cf4797305
--- /dev/null
+++ b/embassy-stm32/src/tl_mbox/mm.rs
@@ -0,0 +1,30 @@
1use core::mem::MaybeUninit;
2
3use super::unsafe_linked_list::LST_init_head;
4use super::{
5 MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUFF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF,
6 TL_MEM_MANAGER_TABLE,
7};
8
9pub struct MemoryManager;
10
11impl MemoryManager {
12 pub fn new() -> Self {
13 unsafe {
14 LST_init_head(FREE_BUFF_QUEUE.as_mut_ptr());
15 LST_init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr());
16
17 TL_MEM_MANAGER_TABLE = MaybeUninit::new(MemManagerTable {
18 spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(),
19 spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(),
20 ble_pool: EVT_POOL.as_ptr().cast(),
21 ble_pool_size: POOL_SIZE as u32,
22 pevt_free_buffer_queue: FREE_BUFF_QUEUE.as_mut_ptr(),
23 traces_evt_pool: core::ptr::null(),
24 traces_pool_size: 0,
25 });
26 }
27
28 MemoryManager
29 }
30}
diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32/src/tl_mbox/mod.rs
new file mode 100644
index 000000000..623546dc9
--- /dev/null
+++ b/embassy-stm32/src/tl_mbox/mod.rs
@@ -0,0 +1,318 @@
1use core::mem::MaybeUninit;
2
3use bit_field::BitField;
4
5use self::ble::Ble;
6use self::cmd::{AclDataPacket, CmdPacket};
7use self::evt::CsEvt;
8use self::mm::MemoryManager;
9use self::sys::Sys;
10use self::unsafe_linked_list::LinkedListNode;
11use crate::ipcc::Ipcc;
12
13mod ble;
14mod channels;
15mod cmd;
16mod evt;
17mod mm;
18mod sys;
19mod unsafe_linked_list;
20
21pub type PacketHeader = LinkedListNode;
22
23const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::<PacketHeader>();
24const TL_EVT_HEADER_SIZE: usize = 3;
25const TL_CS_EVT_SIZE: usize = core::mem::size_of::<CsEvt>();
26
27const CFG_TL_BLE_EVT_QUEUE_LENGTH: usize = 5;
28const CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255;
29const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE;
30
31const POOL_SIZE: usize = CFG_TL_BLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4);
32
33const fn divc(x: usize, y: usize) -> usize {
34 (x + y - 1) / y
35}
36
37#[repr(C, packed)]
38#[derive(Copy, Clone)]
39pub struct SafeBootInfoTable {
40 version: u32,
41}
42
43#[repr(C, packed)]
44#[derive(Copy, Clone)]
45pub struct RssInfoTable {
46 version: u32,
47 memory_size: u32,
48 rss_info: u32,
49}
50
51/// # Version
52/// - 0 -> 3 = Build - 0: Untracked - 15:Released - x: Tracked version
53/// - 4 -> 7 = branch - 0: Mass Market - x: ...
54/// - 8 -> 15 = Subversion
55/// - 16 -> 23 = Version minor
56/// - 24 -> 31 = Version major
57/// # Memory Size
58/// - 0 -> 7 = Flash ( Number of 4k sector)
59/// - 8 -> 15 = Reserved ( Shall be set to 0 - may be used as flash extension )
60/// - 16 -> 23 = SRAM2b ( Number of 1k sector)
61/// - 24 -> 31 = SRAM2a ( Number of 1k sector)
62#[repr(C, packed)]
63#[derive(Copy, Clone)]
64pub struct WirelessFwInfoTable {
65 version: u32,
66 memory_size: u32,
67 thread_info: u32,
68 ble_info: u32,
69}
70
71impl WirelessFwInfoTable {
72 pub fn version_major(&self) -> u8 {
73 let version = self.version;
74 (version.get_bits(24..31) & 0xff) as u8
75 }
76
77 pub fn version_minor(&self) -> u8 {
78 let version = self.version;
79 (version.get_bits(16..23) & 0xff) as u8
80 }
81
82 pub fn subversion(&self) -> u8 {
83 let version = self.version;
84 (version.get_bits(8..15) & 0xff) as u8
85 }
86
87 /// size of FLASH, expressed in number of 4K sectors
88 pub fn flash_size(&self) -> u8 {
89 let memory_size = self.memory_size;
90 (memory_size.get_bits(0..7) & 0xff) as u8
91 }
92
93 /// size for SRAM2a, expressed in number of 1K sectors
94 pub fn sram2a_size(&self) -> u8 {
95 let memory_size = self.memory_size;
96 (memory_size.get_bits(24..31) & 0xff) as u8
97 }
98
99 /// size of SRAM2b, expressed in number of 1K sectors
100 pub fn sram2b_size(&self) -> u8 {
101 let memory_size = self.memory_size;
102 (memory_size.get_bits(16..23) & 0xff) as u8
103 }
104}
105
106#[repr(C, packed)]
107#[derive(Copy, Clone)]
108pub struct DeviceInfoTable {
109 pub safe_boot_info_table: SafeBootInfoTable,
110 pub rss_info_table: RssInfoTable,
111 pub wireless_fw_info_table: WirelessFwInfoTable,
112}
113
114#[repr(C, packed)]
115struct BleTable {
116 pcmd_buffer: *const CmdPacket,
117 pcs_buffer: *const u8,
118 pevt_queue: *const u8,
119 phci_acl_data_buffer: *mut AclDataPacket,
120}
121
122#[repr(C, packed)]
123struct ThreadTable {
124 no_stack_buffer: *const u8,
125 cli_cmd_rsp_buffer: *const u8,
126 ot_cmd_rsp_buffer: *const u8,
127}
128
129#[repr(C, packed)]
130struct SysTable {
131 pcmd_buffer: *mut CmdPacket,
132 sys_queue: *const LinkedListNode,
133}
134
135#[allow(dead_code)] // Not used currently but reserved
136#[repr(C, packed)]
137struct LldTestTable {
138 cli_cmd_rsp_buffer: *const u8,
139 m0_cmd_buffer: *const u8,
140}
141
142#[allow(dead_code)] // Not used currently but reserved
143#[repr(C, packed)]
144struct BleLldTable {
145 cmd_rsp_buffer: *const u8,
146 m0_cmd_buffer: *const u8,
147}
148
149#[allow(dead_code)] // Not used currently but reserved
150#[repr(C, packed)]
151struct ZigbeeTable {
152 notif_m0_to_m4_buffer: *const u8,
153 appli_cmd_m4_to_m0_buffer: *const u8,
154 request_m0_to_m4_buffer: *const u8,
155}
156
157#[repr(C, packed)]
158struct MemManagerTable {
159 spare_ble_buffer: *const u8,
160 spare_sys_buffer: *const u8,
161
162 ble_pool: *const u8,
163 ble_pool_size: u32,
164
165 pevt_free_buffer_queue: *mut LinkedListNode,
166
167 traces_evt_pool: *const u8,
168 traces_pool_size: u32,
169}
170
171#[repr(C, packed)]
172struct TracesTable {
173 traces_queue: *const u8,
174}
175
176#[repr(C, packed)]
177struct Mac802_15_4Table {
178 pcmd_rsp_buffer: *const u8,
179 pnotack_buffer: *const u8,
180 evt_queue: *const u8,
181}
182
183/// reference table. Contains pointers to all other tables
184#[repr(C, packed)]
185#[derive(Copy, Clone)]
186pub struct RefTable {
187 pub device_info_table: *const DeviceInfoTable,
188 ble_table: *const BleTable,
189 thread_table: *const ThreadTable,
190 sys_table: *const SysTable,
191 mem_manager_table: *const MemManagerTable,
192 traces_table: *const TracesTable,
193 mac_802_15_4_table: *const Mac802_15_4Table,
194}
195
196#[link_section = "TL_REF_TABLE"]
197pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit();
198
199#[link_section = "TL_DEVICE_INFO_TABLE"]
200static mut TL_DEVICE_INFO_TABLE: MaybeUninit<DeviceInfoTable> = MaybeUninit::uninit();
201
202#[link_section = "TL_BLE_TABLE"]
203static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit();
204
205#[link_section = "TL_THREAD_TABLE"]
206static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit();
207
208#[link_section = "TL_SYS_TABLE"]
209static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit();
210
211#[link_section = "TL_MEM_MANAGER_TABLE"]
212static mut TL_MEM_MANAGER_TABLE: MaybeUninit<MemManagerTable> = MaybeUninit::uninit();
213
214#[link_section = "TL_TRACES_TABLE"]
215static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit();
216
217#[link_section = "TL_MAC_802_15_4_TABLE"]
218static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit();
219
220#[allow(dead_code)] // Not used currently but reserved
221#[link_section = "FREE_BUF_QUEUE"]
222static mut FREE_BUFF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
223
224// not in shared RAM
225static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
226
227#[allow(dead_code)] // Not used currently but reserved
228#[link_section = "TRACES_EVT_QUEUE"]
229static mut TRACES_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
230
231#[link_section = "CS_BUFFER"]
232static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> =
233 MaybeUninit::uninit();
234
235#[link_section = "EVT_QUEUE"]
236static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
237
238#[link_section = "SYSTEM_EVT_QUEUE"]
239static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
240
241#[link_section = "SYS_CMD_BUF"]
242static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
243
244#[link_section = "EVT_POOL"]
245static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit();
246
247#[link_section = "SYS_SPARE_EVT_BUF"]
248static mut SYS_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
249 MaybeUninit::uninit();
250
251#[link_section = "BLE_SPARE_EVT_BUF"]
252static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
253 MaybeUninit::uninit();
254
255#[link_section = "BLE_CMD_BUFFER"]
256static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
257
258#[link_section = "HCI_ACL_DATA_BUFFER"]
259// "magic" numbers from ST ---v---v
260static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit();
261
262pub struct TlMbox {
263 _sys: Sys,
264 _ble: Ble,
265 _mm: MemoryManager,
266}
267
268impl TlMbox {
269 /// initializes low-level transport between CPU1 and BLE stack on CPU2
270 pub fn init(ipcc: &mut Ipcc) -> TlMbox {
271 unsafe {
272 TL_REF_TABLE = MaybeUninit::new(RefTable {
273 device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(),
274 ble_table: TL_BLE_TABLE.as_ptr(),
275 thread_table: TL_THREAD_TABLE.as_ptr(),
276 sys_table: TL_SYS_TABLE.as_ptr(),
277 mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(),
278 traces_table: TL_TRACES_TABLE.as_ptr(),
279 mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(),
280 });
281
282 TL_SYS_TABLE = MaybeUninit::zeroed();
283 TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed();
284 TL_BLE_TABLE = MaybeUninit::zeroed();
285 TL_THREAD_TABLE = MaybeUninit::zeroed();
286 TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed();
287 TL_TRACES_TABLE = MaybeUninit::zeroed();
288 TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed();
289
290 EVT_POOL = MaybeUninit::zeroed();
291 SYS_SPARE_EVT_BUF = MaybeUninit::zeroed();
292 BLE_SPARE_EVT_BUF = MaybeUninit::zeroed();
293
294 CS_BUFFER = MaybeUninit::zeroed();
295 BLE_CMD_BUFFER = MaybeUninit::zeroed();
296 HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed();
297 }
298
299 ipcc.init();
300
301 let _sys = Sys::new(ipcc);
302 let _ble = Ble::new(ipcc);
303 let _mm = MemoryManager::new();
304
305 TlMbox { _sys, _ble, _mm }
306 }
307
308 pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> {
309 let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table };
310
311 // zero version indicates that CPU2 wasn't active and didn't fill the information table
312 if info.version != 0 {
313 Some(*info)
314 } else {
315 None
316 }
317 }
318}
diff --git a/embassy-stm32/src/tl_mbox/sys.rs b/embassy-stm32/src/tl_mbox/sys.rs
new file mode 100644
index 000000000..13ae7f9f9
--- /dev/null
+++ b/embassy-stm32/src/tl_mbox/sys.rs
@@ -0,0 +1,24 @@
1use core::mem::MaybeUninit;
2
3use super::unsafe_linked_list::LST_init_head;
4use super::{channels, SysTable, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE};
5use crate::ipcc::Ipcc;
6
7pub struct Sys;
8
9impl Sys {
10 pub fn new(ipcc: &mut Ipcc) -> Self {
11 unsafe {
12 LST_init_head(SYSTEM_EVT_QUEUE.as_mut_ptr());
13
14 TL_SYS_TABLE = MaybeUninit::new(SysTable {
15 pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(),
16 sys_queue: SYSTEM_EVT_QUEUE.as_ptr(),
17 });
18 }
19
20 ipcc.c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true);
21
22 Sys
23 }
24}
diff --git a/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs b/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs
new file mode 100644
index 000000000..9caf01d1d
--- /dev/null
+++ b/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs
@@ -0,0 +1,123 @@
1//! Unsafe linked list.
2//! Translated from ST's C by `c2rust` tool.
3
4#![allow(
5 dead_code,
6 mutable_transmutes,
7 non_camel_case_types,
8 non_snake_case,
9 non_upper_case_globals,
10 unused_assignments,
11 unused_mut
12)]
13
14use cortex_m::interrupt;
15
16#[derive(Copy, Clone)]
17#[repr(C, packed(4))]
18pub struct LinkedListNode {
19 pub next: *mut LinkedListNode,
20 pub prev: *mut LinkedListNode,
21}
22
23impl Default for LinkedListNode {
24 fn default() -> Self {
25 LinkedListNode {
26 next: core::ptr::null_mut(),
27 prev: core::ptr::null_mut(),
28 }
29 }
30}
31
32pub unsafe fn LST_init_head(mut listHead: *mut LinkedListNode) {
33 (*listHead).next = listHead;
34 (*listHead).prev = listHead;
35}
36
37pub unsafe fn LST_is_empty(mut listHead: *mut LinkedListNode) -> bool {
38 interrupt::free(|_| ((*listHead).next) == listHead)
39}
40
41pub unsafe fn LST_insert_head(mut listHead: *mut LinkedListNode, mut node: *mut LinkedListNode) {
42 interrupt::free(|_| {
43 (*node).next = (*listHead).next;
44 (*node).prev = listHead;
45 (*listHead).next = node;
46 (*(*node).next).prev = node;
47 });
48}
49
50pub unsafe fn LST_insert_tail(mut listHead: *mut LinkedListNode, mut node: *mut LinkedListNode) {
51 interrupt::free(|_| {
52 (*node).next = listHead;
53 (*node).prev = (*listHead).prev;
54 (*listHead).prev = node;
55 (*(*node).prev).next = node;
56 });
57}
58
59pub unsafe fn LST_remove_node(mut node: *mut LinkedListNode) {
60 interrupt::free(|_| {
61 (*(*node).prev).next = (*node).next;
62 (*(*node).next).prev = (*node).prev;
63 });
64}
65
66pub unsafe fn LST_remove_head(mut listHead: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
67 interrupt::free(|_| {
68 *node = (*listHead).next;
69 LST_remove_node((*listHead).next);
70 });
71}
72
73pub unsafe fn LST_remove_tail(mut listHead: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
74 interrupt::free(|_| {
75 *node = (*listHead).prev;
76 LST_remove_node((*listHead).prev);
77 });
78}
79
80pub unsafe fn LST_insert_node_after(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) {
81 interrupt::free(|_| {
82 (*node).next = (*ref_node).next;
83 (*node).prev = ref_node;
84 (*ref_node).next = node;
85 (*(*node).next).prev = node;
86 });
87}
88
89pub unsafe fn LST_insert_node_before(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) {
90 interrupt::free(|_| {
91 (*node).next = ref_node;
92 (*node).prev = (*ref_node).prev;
93 (*ref_node).prev = node;
94 (*(*node).prev).next = node;
95 });
96}
97
98pub unsafe fn LST_get_size(mut listHead: *mut LinkedListNode) -> usize {
99 interrupt::free(|_| {
100 let mut size = 0;
101 let mut temp: *mut LinkedListNode = core::ptr::null_mut::<LinkedListNode>();
102
103 temp = (*listHead).next;
104 while temp != listHead {
105 size += 1;
106 temp = (*temp).next
107 }
108
109 size
110 })
111}
112
113pub unsafe fn LST_get_next_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
114 interrupt::free(|_| {
115 *node = (*ref_node).next;
116 });
117}
118
119pub unsafe fn LST_get_prev_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
120 interrupt::free(|_| {
121 *node = (*ref_node).prev;
122 });
123}