aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
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
parentce1d72c609ae1e04410e68458ec3d6c36c7dae27 (diff)
stm32/ipcc: move tl_mbox into `embassy-stm32-wpan`
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/src/ipcc.rs (renamed from embassy-stm32/src/tl_mbox/ipcc.rs)60
-rw-r--r--embassy-stm32/src/lib.rs4
-rw-r--r--embassy-stm32/src/tl_mbox/ble.rs81
-rw-r--r--embassy-stm32/src/tl_mbox/channels.rs104
-rw-r--r--embassy-stm32/src/tl_mbox/cmd.rs77
-rw-r--r--embassy-stm32/src/tl_mbox/consts.rs55
-rw-r--r--embassy-stm32/src/tl_mbox/evt.rs176
-rw-r--r--embassy-stm32/src/tl_mbox/hci.rs60
-rw-r--r--embassy-stm32/src/tl_mbox/mm.rs75
-rw-r--r--embassy-stm32/src/tl_mbox/mod.rs446
-rw-r--r--embassy-stm32/src/tl_mbox/shci.rs100
-rw-r--r--embassy-stm32/src/tl_mbox/sys.rs76
-rw-r--r--embassy-stm32/src/tl_mbox/unsafe_linked_list.rs125
13 files changed, 62 insertions, 1377 deletions
diff --git a/embassy-stm32/src/tl_mbox/ipcc.rs b/embassy-stm32/src/ipcc.rs
index d1ac731ed..8bb0774b8 100644
--- a/embassy-stm32/src/tl_mbox/ipcc.rs
+++ b/embassy-stm32/src/ipcc.rs
@@ -167,8 +167,68 @@ impl sealed::Instance for crate::peripherals::IPCC {
167} 167}
168 168
169unsafe fn _configure_pwr() { 169unsafe fn _configure_pwr() {
170 let pwr = crate::pac::PWR;
170 let rcc = crate::pac::RCC; 171 let rcc = crate::pac::RCC;
171 172
173 rcc.cfgr().modify(|w| w.set_stopwuck(true));
174
175 pwr.cr1().modify(|w| w.set_dbp(true));
176 pwr.cr1().modify(|w| w.set_dbp(true));
177
178 // configure LSE
179 rcc.bdcr().modify(|w| w.set_lseon(true));
180
181 // select system clock source = PLL
182 // set PLL coefficients
183 // m: 2,
184 // n: 12,
185 // r: 3,
186 // q: 4,
187 // p: 3,
188 let src_bits = 0b11;
189 let pllp = (3 - 1) & 0b11111;
190 let pllq = (4 - 1) & 0b111;
191 let pllr = (3 - 1) & 0b111;
192 let plln = 12 & 0b1111111;
193 let pllm = (2 - 1) & 0b111;
194 rcc.pllcfgr().modify(|w| {
195 w.set_pllsrc(src_bits);
196 w.set_pllm(pllm);
197 w.set_plln(plln);
198 w.set_pllr(pllr);
199 w.set_pllp(pllp);
200 w.set_pllpen(true);
201 w.set_pllq(pllq);
202 w.set_pllqen(true);
203 });
204 // enable PLL
205 rcc.cr().modify(|w| w.set_pllon(true));
206 rcc.cr().write(|w| w.set_hsion(false));
207 // while !rcc.cr().read().pllrdy() {}
208
209 // configure SYSCLK mux to use PLL clocl
210 rcc.cfgr().modify(|w| w.set_sw(0b11));
211
212 // configure CPU1 & CPU2 dividers
213 rcc.cfgr().modify(|w| w.set_hpre(0)); // not divided
214 rcc.extcfgr().modify(|w| {
215 w.set_c2hpre(0b1000); // div2
216 w.set_shdhpre(0); // not divided
217 });
218
219 // apply APB1 / APB2 values
220 rcc.cfgr().modify(|w| {
221 w.set_ppre1(0b000); // not divided
222 w.set_ppre2(0b000); // not divided
223 });
224
225 // TODO: required
172 // set RF wake-up clock = LSE 226 // set RF wake-up clock = LSE
173 rcc.csr().modify(|w| w.set_rfwkpsel(0b01)); 227 rcc.csr().modify(|w| w.set_rfwkpsel(0b01));
228
229 // set LPTIM1 & LPTIM2 clock source
230 rcc.ccipr().modify(|w| {
231 w.set_lptim1sel(0b00); // PCLK
232 w.set_lptim2sel(0b00); // PCLK
233 });
174} 234}
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 75d8af3dd..8c13774a0 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -41,6 +41,8 @@ pub mod crc;
41pub mod flash; 41pub mod flash;
42#[cfg(all(spi_v1, rcc_f4))] 42#[cfg(all(spi_v1, rcc_f4))]
43pub mod i2s; 43pub mod i2s;
44#[cfg(stm32wb)]
45pub mod ipcc;
44pub mod pwm; 46pub mod pwm;
45#[cfg(quadspi)] 47#[cfg(quadspi)]
46pub mod qspi; 48pub mod qspi;
@@ -52,8 +54,6 @@ pub mod rtc;
52pub mod sdmmc; 54pub mod sdmmc;
53#[cfg(spi)] 55#[cfg(spi)]
54pub mod spi; 56pub mod spi;
55#[cfg(stm32wb)]
56pub mod tl_mbox;
57#[cfg(usart)] 57#[cfg(usart)]
58pub mod usart; 58pub mod usart;
59#[cfg(usb)] 59#[cfg(usb)]
diff --git a/embassy-stm32/src/tl_mbox/ble.rs b/embassy-stm32/src/tl_mbox/ble.rs
deleted file mode 100644
index 45bf81ef2..000000000
--- a/embassy-stm32/src/tl_mbox/ble.rs
+++ /dev/null
@@ -1,81 +0,0 @@
1use embassy_futures::block_on;
2
3use super::cmd::{CmdPacket, CmdSerial};
4use super::consts::TlPacketType;
5use super::evt::EvtBox;
6use super::ipcc::Ipcc;
7use super::unsafe_linked_list::LinkedListNode;
8use super::{
9 channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, HEAPLESS_EVT_QUEUE, TL_BLE_TABLE,
10 TL_REF_TABLE,
11};
12
13pub struct Ble;
14
15impl Ble {
16 pub(super) fn new() -> Self {
17 unsafe {
18 LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr());
19
20 TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable {
21 pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(),
22 pcs_buffer: CS_BUFFER.as_ptr().cast(),
23 pevt_queue: EVT_QUEUE.as_ptr().cast(),
24 phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(),
25 });
26 }
27
28 Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true);
29
30 Ble
31 }
32
33 pub(super) fn evt_handler() {
34 unsafe {
35 let mut node_ptr = core::ptr::null_mut();
36 let node_ptr_ptr: *mut _ = &mut node_ptr;
37
38 while !LinkedListNode::is_empty(EVT_QUEUE.as_mut_ptr()) {
39 LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr(), node_ptr_ptr);
40
41 let event = node_ptr.cast();
42 let event = EvtBox::new(event);
43
44 block_on(HEAPLESS_EVT_QUEUE.send(event));
45 }
46 }
47
48 Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL);
49 }
50
51 pub(super) fn acl_data_handler(&self) {
52 Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, false);
53
54 // TODO: ACL data ack to the user
55 }
56
57 pub fn send_cmd(buf: &[u8]) {
58 unsafe {
59 let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer;
60 let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmdserial;
61 let pcmd_serial_buf: *mut u8 = pcmd_serial.cast();
62
63 core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len());
64
65 let mut cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer;
66 cmd_packet.cmdserial.ty = TlPacketType::BleCmd as u8;
67 }
68
69 Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL);
70 }
71
72 #[allow(dead_code)] // Not used currently but reserved
73 pub(super) fn send_acl_data() {
74 let cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer };
75
76 cmd_packet.acl_data_serial.ty = TlPacketType::AclData as u8;
77
78 Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL);
79 Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, true);
80 }
81}
diff --git a/embassy-stm32/src/tl_mbox/channels.rs b/embassy-stm32/src/tl_mbox/channels.rs
deleted file mode 100644
index 25a065ba4..000000000
--- a/embassy-stm32/src/tl_mbox/channels.rs
+++ /dev/null
@@ -1,104 +0,0 @@
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::tl_mbox::ipcc::IpccChannel;
54
55 // Not used currently but reserved
56 pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1;
57 // 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 // 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::tl_mbox::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
deleted file mode 100644
index 781aa669d..000000000
--- a/embassy-stm32/src/tl_mbox/cmd.rs
+++ /dev/null
@@ -1,77 +0,0 @@
1use crate::tl_mbox::evt::{EvtPacket, EvtSerial};
2use crate::tl_mbox::{PacketHeader, TL_EVT_HEADER_SIZE};
3
4#[derive(Copy, Clone)]
5#[repr(C, packed)]
6pub struct Cmd {
7 pub cmd_code: u16,
8 pub payload_len: u8,
9 pub payload: [u8; 255],
10}
11
12impl Default for Cmd {
13 fn default() -> Self {
14 Self {
15 cmd_code: 0,
16 payload_len: 0,
17 payload: [0u8; 255],
18 }
19 }
20}
21
22#[derive(Copy, Clone, Default)]
23#[repr(C, packed)]
24pub struct CmdSerial {
25 pub ty: u8,
26 pub cmd: Cmd,
27}
28
29#[derive(Copy, Clone, Default)]
30#[repr(C, packed)]
31pub struct CmdPacket {
32 pub header: PacketHeader,
33 pub cmdserial: CmdSerial,
34}
35
36impl CmdPacket {
37 /// Writes an underlying CmdPacket into the provided buffer.
38 /// Returns a number of bytes that were written.
39 /// Returns an error if event kind is unknown or if provided buffer size is not enough.
40 #[allow(clippy::result_unit_err)]
41 pub fn write(&self, buf: &mut [u8]) -> Result<usize, ()> {
42 unsafe {
43 let cmd_ptr: *const CmdPacket = self;
44 let self_as_evt_ptr: *const EvtPacket = cmd_ptr.cast();
45 let evt_serial: *const EvtSerial = &(*self_as_evt_ptr).evt_serial;
46
47 let acl_data: *const AclDataPacket = cmd_ptr.cast();
48 let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial;
49 let acl_serial_buf: *const u8 = acl_serial.cast();
50
51 let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE;
52 if len > buf.len() {
53 return Err(());
54 }
55
56 core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len);
57
58 Ok(len)
59 }
60 }
61}
62
63#[derive(Copy, Clone)]
64#[repr(C, packed)]
65pub struct AclDataSerial {
66 pub ty: u8,
67 pub handle: u16,
68 pub length: u16,
69 pub acl_data: [u8; 1],
70}
71
72#[derive(Copy, Clone)]
73#[repr(C, packed)]
74pub struct AclDataPacket {
75 pub header: PacketHeader,
76 pub acl_data_serial: AclDataSerial,
77}
diff --git a/embassy-stm32/src/tl_mbox/consts.rs b/embassy-stm32/src/tl_mbox/consts.rs
deleted file mode 100644
index caf26c06b..000000000
--- a/embassy-stm32/src/tl_mbox/consts.rs
+++ /dev/null
@@ -1,55 +0,0 @@
1use core::convert::TryFrom;
2
3#[derive(Debug)]
4#[repr(C)]
5pub enum TlPacketType {
6 BleCmd = 0x01,
7 AclData = 0x02,
8 BleEvt = 0x04,
9
10 OtCmd = 0x08,
11 OtRsp = 0x09,
12 CliCmd = 0x0A,
13 OtNot = 0x0C,
14 OtAck = 0x0D,
15 CliNot = 0x0E,
16 CliAck = 0x0F,
17
18 SysCmd = 0x10,
19 SysRsp = 0x11,
20 SysEvt = 0x12,
21
22 LocCmd = 0x20,
23 LocRsp = 0x21,
24
25 TracesApp = 0x40,
26 TracesWl = 0x41,
27}
28
29impl TryFrom<u8> for TlPacketType {
30 type Error = ();
31
32 fn try_from(value: u8) -> Result<Self, Self::Error> {
33 match value {
34 0x01 => Ok(TlPacketType::BleCmd),
35 0x02 => Ok(TlPacketType::AclData),
36 0x04 => Ok(TlPacketType::BleEvt),
37 0x08 => Ok(TlPacketType::OtCmd),
38 0x09 => Ok(TlPacketType::OtRsp),
39 0x0A => Ok(TlPacketType::CliCmd),
40 0x0C => Ok(TlPacketType::OtNot),
41 0x0D => Ok(TlPacketType::OtAck),
42 0x0E => Ok(TlPacketType::CliNot),
43 0x0F => Ok(TlPacketType::CliAck),
44 0x10 => Ok(TlPacketType::SysCmd),
45 0x11 => Ok(TlPacketType::SysRsp),
46 0x12 => Ok(TlPacketType::SysEvt),
47 0x20 => Ok(TlPacketType::LocCmd),
48 0x21 => Ok(TlPacketType::LocRsp),
49 0x40 => Ok(TlPacketType::TracesApp),
50 0x41 => Ok(TlPacketType::TracesWl),
51
52 _ => Err(()),
53 }
54 }
55}
diff --git a/embassy-stm32/src/tl_mbox/evt.rs b/embassy-stm32/src/tl_mbox/evt.rs
deleted file mode 100644
index 77ce7b4ca..000000000
--- a/embassy-stm32/src/tl_mbox/evt.rs
+++ /dev/null
@@ -1,176 +0,0 @@
1use core::mem::MaybeUninit;
2
3use super::cmd::{AclDataPacket, AclDataSerial};
4use super::consts::TlPacketType;
5use super::mm::MemoryManager;
6use super::{PacketHeader, TL_EVT_HEADER_SIZE};
7
8/**
9 * The payload of `Evt` for a command status event
10 */
11#[derive(Debug, Copy, Clone)]
12#[repr(C, packed)]
13pub struct CsEvt {
14 pub status: u8,
15 pub num_cmd: u8,
16 pub cmd_code: u16,
17}
18
19/**
20 * The payload of `Evt` for a command complete event
21 */
22#[derive(Debug, Copy, Clone, Default)]
23#[repr(C, packed)]
24pub struct CcEvt {
25 pub num_cmd: u8,
26 pub cmd_code: u16,
27 pub payload: [u8; 1],
28}
29
30impl CcEvt {
31 pub fn write(&self, buf: &mut [u8]) {
32 unsafe {
33 let len = core::mem::size_of::<CcEvt>();
34 assert!(buf.len() >= len);
35
36 let self_ptr: *const CcEvt = self;
37 let self_buf_ptr: *const u8 = self_ptr.cast();
38
39 core::ptr::copy(self_buf_ptr, buf.as_mut_ptr(), len);
40 }
41 }
42}
43
44#[derive(Debug, Copy, Clone, Default)]
45#[repr(C, packed)]
46pub struct AsynchEvt {
47 sub_evt_code: u16,
48 payload: [u8; 1],
49}
50
51#[derive(Debug, Copy, Clone, Default)]
52#[repr(C, packed)]
53pub struct Evt {
54 pub evt_code: u8,
55 pub payload_len: u8,
56 pub payload: [u8; 1],
57}
58
59#[derive(Debug, Copy, Clone, Default)]
60#[repr(C, packed)]
61pub struct EvtSerial {
62 pub kind: u8,
63 pub evt: Evt,
64}
65
66/// This format shall be used for all events (asynchronous and command response) reported
67/// by the CPU2 except for the command response of a system command where the header is not there
68/// and the format to be used shall be `EvtSerial`.
69///
70/// ### Note:
71/// Be careful that the asynchronous events reported by the CPU2 on the system channel do
72/// include the header and shall use `EvtPacket` format. Only the command response format on the
73/// system channel is different.
74#[derive(Copy, Clone, Default)]
75#[repr(C, packed)]
76pub struct EvtPacket {
77 pub header: PacketHeader,
78 pub evt_serial: EvtSerial,
79}
80
81impl EvtPacket {
82 pub fn kind(&self) -> u8 {
83 self.evt_serial.kind
84 }
85
86 pub fn evt(&self) -> &Evt {
87 &self.evt_serial.evt
88 }
89}
90
91/// smart pointer to the [`EvtPacket`] that will dispose of [`EvtPacket`] buffer automatically
92/// on [`Drop`]
93#[derive(Debug)]
94pub struct EvtBox {
95 ptr: *mut EvtPacket,
96}
97
98unsafe impl Send for EvtBox {}
99impl EvtBox {
100 pub(super) fn new(ptr: *mut EvtPacket) -> Self {
101 Self { ptr }
102 }
103
104 /// copies event data from inner pointer and returns an event structure
105 pub fn evt(&self) -> EvtPacket {
106 let mut evt = MaybeUninit::uninit();
107 unsafe {
108 self.ptr.copy_to(evt.as_mut_ptr(), 1);
109 evt.assume_init()
110 }
111 }
112
113 /// writes an underlying [`EvtPacket`] into the provided buffer.
114 /// Returns the number of bytes that were written.
115 /// Returns an error if event kind is unknown or if provided buffer size is not enough.
116 #[allow(clippy::result_unit_err)]
117 pub fn write(&self, buf: &mut [u8]) -> Result<usize, ()> {
118 unsafe {
119 let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?;
120
121 let evt_data: *const EvtPacket = self.ptr.cast();
122 let evt_serial: *const EvtSerial = &(*evt_data).evt_serial;
123 let evt_serial_buf: *const u8 = evt_serial.cast();
124
125 let acl_data: *const AclDataPacket = self.ptr.cast();
126 let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial;
127 let acl_serial_buf: *const u8 = acl_serial.cast();
128
129 if let TlPacketType::AclData = evt_kind {
130 let len = (*acl_serial).length as usize + 5;
131 if len > buf.len() {
132 return Err(());
133 }
134
135 core::ptr::copy(evt_serial_buf, buf.as_mut_ptr(), len);
136
137 Ok(len)
138 } else {
139 let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE;
140 if len > buf.len() {
141 return Err(());
142 }
143
144 core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len);
145
146 Ok(len)
147 }
148 }
149 }
150
151 /// returns the size of a buffer required to hold this event
152 #[allow(clippy::result_unit_err)]
153 pub fn size(&self) -> Result<usize, ()> {
154 unsafe {
155 let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?;
156
157 let evt_data: *const EvtPacket = self.ptr.cast();
158 let evt_serial: *const EvtSerial = &(*evt_data).evt_serial;
159
160 let acl_data: *const AclDataPacket = self.ptr.cast();
161 let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial;
162
163 if let TlPacketType::AclData = evt_kind {
164 Ok((*acl_serial).length as usize + 5)
165 } else {
166 Ok((*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE)
167 }
168 }
169 }
170}
171
172impl Drop for EvtBox {
173 fn drop(&mut self) {
174 MemoryManager::evt_drop(self.ptr);
175 }
176}
diff --git a/embassy-stm32/src/tl_mbox/hci.rs b/embassy-stm32/src/tl_mbox/hci.rs
deleted file mode 100644
index 5bb4ba666..000000000
--- a/embassy-stm32/src/tl_mbox/hci.rs
+++ /dev/null
@@ -1,60 +0,0 @@
1use super::ble::Ble;
2use super::consts::TlPacketType;
3use super::evt::CcEvt;
4use super::shci::{shci_ble_init, ShciBleInitCmdParam};
5use super::{TlMbox, STATE};
6
7pub struct RadioCoprocessor<'d> {
8 mbox: TlMbox<'d>,
9 config: ShciBleInitCmdParam,
10 rx_buffer: [u8; 500],
11}
12
13impl<'d> RadioCoprocessor<'d> {
14 pub fn new(mbox: TlMbox<'d>, config: ShciBleInitCmdParam) -> Self {
15 Self {
16 mbox,
17 config,
18 rx_buffer: [0u8; 500],
19 }
20 }
21
22 pub fn write(&mut self, params: &[u8]) -> Result<(), ()> {
23 let cmd_code = params[0];
24 let cmd = TlPacketType::try_from(cmd_code)?;
25
26 match cmd {
27 TlPacketType::BleCmd => Ble::send_cmd(params),
28 _ => todo!(),
29 }
30
31 Ok(())
32 }
33
34 pub async fn read(&mut self) -> &[u8] {
35 self.rx_buffer = [0u8; 500];
36
37 loop {
38 STATE.wait().await;
39
40 if let Some(evt) = self.mbox.dequeue_event() {
41 let event = evt.evt();
42 evt.write(&mut self.rx_buffer).unwrap();
43
44 if event.kind() == 18 {
45 shci_ble_init(self.config);
46 self.rx_buffer[0] = 0x04; // replace event code with one that is supported by HCI
47 }
48
49 if let Some(cc) = self.mbox.pop_last_cc_evt() {
50
51
52 continue;
53 }
54
55 let payload_len = self.rx_buffer[2];
56 return &self.rx_buffer[..3 + payload_len as usize];
57 }
58 }
59 }
60}
diff --git a/embassy-stm32/src/tl_mbox/mm.rs b/embassy-stm32/src/tl_mbox/mm.rs
deleted file mode 100644
index a40438499..000000000
--- a/embassy-stm32/src/tl_mbox/mm.rs
+++ /dev/null
@@ -1,75 +0,0 @@
1//! Memory manager routines
2
3use core::mem::MaybeUninit;
4
5use super::evt::EvtPacket;
6use super::ipcc::Ipcc;
7use super::unsafe_linked_list::LinkedListNode;
8use super::{
9 channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE,
10 SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, TL_REF_TABLE,
11};
12
13pub(super) struct MemoryManager;
14
15impl MemoryManager {
16 pub fn new() -> Self {
17 unsafe {
18 LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr());
19 LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr());
20
21 TL_MEM_MANAGER_TABLE = MaybeUninit::new(MemManagerTable {
22 spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(),
23 spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(),
24 blepool: EVT_POOL.as_ptr().cast(),
25 blepoolsize: POOL_SIZE as u32,
26 pevt_free_buffer_queue: FREE_BUF_QUEUE.as_mut_ptr(),
27 traces_evt_pool: core::ptr::null(),
28 tracespoolsize: 0,
29 });
30 }
31
32 MemoryManager
33 }
34
35 pub fn evt_drop(evt: *mut EvtPacket) {
36 unsafe {
37 let list_node = evt.cast();
38
39 LinkedListNode::insert_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node);
40
41 let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL);
42
43 // postpone event buffer freeing to IPCC interrupt handler
44 if channel_is_busy {
45 Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true);
46 } else {
47 Self::send_free_buf();
48 Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL);
49 }
50 }
51 }
52
53 /// gives free event buffers back to CPU2 from local buffer queue
54 pub fn send_free_buf() {
55 unsafe {
56 let mut node_ptr = core::ptr::null_mut();
57 let node_ptr_ptr: *mut _ = &mut node_ptr;
58
59 while !LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) {
60 LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), node_ptr_ptr);
61 LinkedListNode::insert_tail(
62 (*(*TL_REF_TABLE.as_ptr()).mem_manager_table).pevt_free_buffer_queue,
63 node_ptr,
64 );
65 }
66 }
67 }
68
69 /// free buffer channel interrupt handler
70 pub fn free_buf_handler() {
71 Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false);
72 Self::send_free_buf();
73 Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL);
74 }
75}
diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32/src/tl_mbox/mod.rs
deleted file mode 100644
index 21a954417..000000000
--- a/embassy-stm32/src/tl_mbox/mod.rs
+++ /dev/null
@@ -1,446 +0,0 @@
1use core::mem::MaybeUninit;
2
3use bit_field::BitField;
4use embassy_cortex_m::interrupt::Interrupt;
5use embassy_futures::block_on;
6use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
8use embassy_sync::channel::Channel;
9use embassy_sync::signal::Signal;
10
11use self::cmd::{AclDataPacket, CmdPacket};
12use self::evt::{CcEvt, EvtBox};
13use self::ipcc::{Config, Ipcc};
14use self::unsafe_linked_list::LinkedListNode;
15use crate::interrupt;
16use crate::peripherals::IPCC;
17
18pub mod ble;
19pub mod channels;
20pub mod cmd;
21pub mod consts;
22pub mod evt;
23pub mod hci;
24pub mod ipcc;
25pub mod mm;
26pub mod shci;
27pub mod sys;
28pub mod unsafe_linked_list;
29
30/// Interrupt handler.
31pub struct ReceiveInterruptHandler {}
32
33impl interrupt::Handler<interrupt::IPCC_C1_RX> for ReceiveInterruptHandler {
34 unsafe fn on_interrupt() {
35 debug!("ipcc rx interrupt");
36
37 if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) {
38 debug!("sys evt");
39 sys::Sys::evt_handler();
40 } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) {
41 debug!("ble evt");
42 ble::Ble::evt_handler();
43 } else {
44 todo!()
45 }
46
47 STATE.signal(());
48 }
49}
50
51pub struct TransmitInterruptHandler {}
52
53impl interrupt::Handler<interrupt::IPCC_C1_TX> for TransmitInterruptHandler {
54 unsafe fn on_interrupt() {
55 debug!("ipcc tx interrupt");
56
57 if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) {
58 debug!("sys cmd rsp");
59 // TODO: handle this case
60 let cc = sys::Sys::cmd_evt_handler();
61 let a = unsafe { core::slice::from_raw_parts(&cc as *const _ as *const u8, core::mem::size_of::<CcEvt>()) };
62 debug!("{:#04x}", a);
63
64 LAST_CC_EVT.signal(cc);
65 } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) {
66 debug!("mm");
67 mm::MemoryManager::free_buf_handler();
68 } else {
69 todo!()
70 }
71
72 STATE.signal(());
73 }
74}
75
76#[derive(Debug, Copy, Clone)]
77#[repr(C, packed)]
78pub struct SafeBootInfoTable {
79 version: u32,
80}
81
82#[derive(Debug, Copy, Clone)]
83#[repr(C, packed)]
84pub struct RssInfoTable {
85 version: u32,
86 memory_size: u32,
87 rss_info: u32,
88}
89
90/**
91 * Version
92 * [0:3] = Build - 0: Untracked - 15:Released - x: Tracked version
93 * [4:7] = branch - 0: Mass Market - x: ...
94 * [8:15] = Subversion
95 * [16:23] = Version minor
96 * [24:31] = Version major
97 *
98 * Memory Size
99 * [0:7] = Flash ( Number of 4k sector)
100 * [8:15] = Reserved ( Shall be set to 0 - may be used as flash extension )
101 * [16:23] = SRAM2b ( Number of 1k sector)
102 * [24:31] = SRAM2a ( Number of 1k sector)
103 */
104#[derive(Debug, Copy, Clone)]
105#[repr(C, packed)]
106pub struct WirelessFwInfoTable {
107 version: u32,
108 memory_size: u32,
109 thread_info: u32,
110 ble_info: u32,
111}
112
113impl WirelessFwInfoTable {
114 pub fn version_major(&self) -> u8 {
115 let version = self.version;
116 (version.get_bits(24..31) & 0xff) as u8
117 }
118
119 pub fn version_minor(&self) -> u8 {
120 let version = self.version;
121 (version.clone().get_bits(16..23) & 0xff) as u8
122 }
123
124 pub fn subversion(&self) -> u8 {
125 let version = self.version;
126 (version.clone().get_bits(8..15) & 0xff) as u8
127 }
128
129 /// Size of FLASH, expressed in number of 4K sectors.
130 pub fn flash_size(&self) -> u8 {
131 let memory_size = self.memory_size;
132 (memory_size.clone().get_bits(0..7) & 0xff) as u8
133 }
134
135 /// Size of SRAM2a, expressed in number of 1K sectors.
136 pub fn sram2a_size(&self) -> u8 {
137 let memory_size = self.memory_size;
138 (memory_size.clone().get_bits(24..31) & 0xff) as u8
139 }
140
141 /// Size of SRAM2b, expressed in number of 1K sectors.
142 pub fn sram2b_size(&self) -> u8 {
143 let memory_size = self.memory_size;
144 (memory_size.clone().get_bits(16..23) & 0xff) as u8
145 }
146}
147
148#[derive(Debug, Clone)]
149#[repr(C, align(4))]
150pub struct DeviceInfoTable {
151 pub safe_boot_info_table: SafeBootInfoTable,
152 pub rss_info_table: RssInfoTable,
153 pub wireless_fw_info_table: WirelessFwInfoTable,
154}
155
156#[derive(Debug)]
157#[repr(C, align(4))]
158struct BleTable {
159 pcmd_buffer: *mut CmdPacket,
160 pcs_buffer: *const u8,
161 pevt_queue: *const u8,
162 phci_acl_data_buffer: *mut AclDataPacket,
163}
164
165#[derive(Debug)]
166#[repr(C, align(4))]
167struct ThreadTable {
168 nostack_buffer: *const u8,
169 clicmdrsp_buffer: *const u8,
170 otcmdrsp_buffer: *const u8,
171}
172
173// TODO: use later
174#[derive(Debug)]
175#[repr(C, align(4))]
176pub struct LldTestsTable {
177 clicmdrsp_buffer: *const u8,
178 m0cmd_buffer: *const u8,
179}
180
181// TODO: use later
182#[derive(Debug)]
183#[repr(C, align(4))]
184pub struct BleLldTable {
185 cmdrsp_buffer: *const u8,
186 m0cmd_buffer: *const u8,
187}
188
189// TODO: use later
190#[derive(Debug)]
191#[repr(C, align(4))]
192pub struct ZigbeeTable {
193 notif_m0_to_m4_buffer: *const u8,
194 appli_cmd_m4_to_m0_bufer: *const u8,
195 request_m0_to_m4_buffer: *const u8,
196}
197
198#[derive(Debug)]
199#[repr(C, align(4))]
200struct SysTable {
201 pcmd_buffer: *mut CmdPacket,
202 sys_queue: *const LinkedListNode,
203}
204
205#[derive(Debug)]
206#[repr(C, align(4))]
207struct MemManagerTable {
208 spare_ble_buffer: *const u8,
209 spare_sys_buffer: *const u8,
210
211 blepool: *const u8,
212 blepoolsize: u32,
213
214 pevt_free_buffer_queue: *mut LinkedListNode,
215
216 traces_evt_pool: *const u8,
217 tracespoolsize: u32,
218}
219
220#[derive(Debug)]
221#[repr(C, align(4))]
222struct TracesTable {
223 traces_queue: *const u8,
224}
225
226#[derive(Debug)]
227#[repr(C, align(4))]
228struct Mac802_15_4Table {
229 p_cmdrsp_buffer: *const u8,
230 p_notack_buffer: *const u8,
231 evt_queue: *const u8,
232}
233
234/// Reference table. Contains pointers to all other tables.
235#[derive(Debug, Copy, Clone)]
236#[repr(C)]
237pub struct RefTable {
238 device_info_table: *const DeviceInfoTable,
239 ble_table: *const BleTable,
240 thread_table: *const ThreadTable,
241 sys_table: *const SysTable,
242 mem_manager_table: *const MemManagerTable,
243 traces_table: *const TracesTable,
244 mac_802_15_4_table: *const Mac802_15_4Table,
245}
246
247#[link_section = "TL_REF_TABLE"]
248pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit();
249
250#[link_section = "MB_MEM1"]
251static mut TL_DEVICE_INFO_TABLE: MaybeUninit<DeviceInfoTable> = MaybeUninit::uninit();
252
253#[link_section = "MB_MEM1"]
254static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit();
255
256#[link_section = "MB_MEM1"]
257static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit();
258
259#[link_section = "MB_MEM1"]
260static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit();
261
262#[link_section = "MB_MEM1"]
263static mut TL_MEM_MANAGER_TABLE: MaybeUninit<MemManagerTable> = MaybeUninit::uninit();
264
265#[link_section = "MB_MEM1"]
266static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit();
267
268#[link_section = "MB_MEM1"]
269static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit();
270
271#[link_section = "MB_MEM2"]
272static mut FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
273
274// Not in shared RAM
275static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
276
277#[allow(dead_code)] // Not used currently but reserved
278#[link_section = "MB_MEM2"]
279static mut TRACES_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
280
281type PacketHeader = LinkedListNode;
282
283const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::<PacketHeader>();
284const TL_EVT_HEADER_SIZE: usize = 3;
285const TL_CS_EVT_SIZE: usize = core::mem::size_of::<evt::CsEvt>();
286
287#[link_section = "MB_MEM2"]
288static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> =
289 MaybeUninit::uninit();
290
291#[link_section = "MB_MEM2"]
292static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
293
294#[link_section = "MB_MEM2"]
295static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
296
297#[link_section = "MB_MEM2"]
298pub static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
299
300/**
301 * Queue length of BLE Event
302 * This parameter defines the number of asynchronous events that can be stored in the HCI layer before
303 * being reported to the application. When a command is sent to the BLE core coprocessor, the HCI layer
304 * is waiting for the event with the Num_HCI_Command_Packets set to 1. The receive queue shall be large
305 * enough to store all asynchronous events received in between.
306 * When CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE is set to 27, this allow to store three 255 bytes long asynchronous events
307 * between the HCI command and its event.
308 * This parameter depends on the value given to CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE. When the queue size is to small,
309 * the system may hang if the queue is full with asynchronous events and the HCI layer is still waiting
310 * for a CC/CS event, In that case, the notification TL_BLE_HCI_ToNot() is called to indicate
311 * to the application a HCI command did not receive its command event within 30s (Default HCI Timeout).
312 */
313const CFG_TLBLE_EVT_QUEUE_LENGTH: usize = 5;
314const CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255;
315const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE;
316
317const fn divc(x: usize, y: usize) -> usize {
318 ((x) + (y) - 1) / (y)
319}
320
321const POOL_SIZE: usize = CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4);
322
323#[link_section = "MB_MEM2"]
324static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit();
325
326#[link_section = "MB_MEM2"]
327static mut SYS_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
328 MaybeUninit::uninit();
329
330#[link_section = "MB_MEM2"]
331static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
332 MaybeUninit::uninit();
333
334#[link_section = "MB_MEM2"]
335static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
336
337#[link_section = "MB_MEM2"]
338// fuck these "magic" numbers from ST ---v---v
339static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit();
340
341static HEAPLESS_EVT_QUEUE: Channel<CriticalSectionRawMutex, EvtBox, 32> = Channel::new();
342
343static STATE: Signal<CriticalSectionRawMutex, ()> = Signal::new();
344
345/// current event that is produced during IPCC IRQ handler execution
346/// on SYS channel
347/// last received Command Complete event
348static LAST_CC_EVT: Signal<CriticalSectionRawMutex, CcEvt> = Signal::new();
349
350pub struct TlMbox<'d> {
351 sys: sys::Sys,
352 ble: ble::Ble,
353 _mm: mm::MemoryManager,
354
355 _ipcc: PeripheralRef<'d, IPCC>,
356}
357
358impl<'d> TlMbox<'d> {
359 pub fn new(
360 ipcc: impl Peripheral<P = IPCC> + 'd,
361 _irqs: impl interrupt::Binding<interrupt::IPCC_C1_RX, ReceiveInterruptHandler>
362 + interrupt::Binding<interrupt::IPCC_C1_TX, TransmitInterruptHandler>,
363 config: Config,
364 ) -> Self {
365 into_ref!(ipcc);
366
367 unsafe {
368 TL_REF_TABLE.as_mut_ptr().write_volatile(RefTable {
369 device_info_table: TL_DEVICE_INFO_TABLE.as_mut_ptr(),
370 ble_table: TL_BLE_TABLE.as_ptr(),
371 thread_table: TL_THREAD_TABLE.as_ptr(),
372 sys_table: TL_SYS_TABLE.as_ptr(),
373 mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(),
374 traces_table: TL_TRACES_TABLE.as_ptr(),
375 mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(),
376 });
377
378 TL_SYS_TABLE = MaybeUninit::zeroed();
379 TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed();
380 TL_BLE_TABLE = MaybeUninit::zeroed();
381 TL_THREAD_TABLE = MaybeUninit::zeroed();
382 TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed();
383 TL_TRACES_TABLE = MaybeUninit::zeroed();
384 TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed();
385
386 EVT_POOL = MaybeUninit::zeroed();
387 SYS_SPARE_EVT_BUF = MaybeUninit::zeroed();
388 BLE_SPARE_EVT_BUF = MaybeUninit::zeroed();
389
390 CS_BUFFER = MaybeUninit::zeroed();
391 BLE_CMD_BUFFER = MaybeUninit::zeroed();
392 HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed();
393 }
394
395 Ipcc::enable(config);
396
397 let sys = sys::Sys::new();
398 let ble = ble::Ble::new();
399 let mm = mm::MemoryManager::new();
400
401 // enable interrupts
402 crate::interrupt::IPCC_C1_RX::unpend();
403 crate::interrupt::IPCC_C1_TX::unpend();
404
405 unsafe { crate::interrupt::IPCC_C1_RX::enable() };
406 unsafe { crate::interrupt::IPCC_C1_TX::enable() };
407
408 Self {
409 sys,
410 ble,
411 _mm: mm,
412 _ipcc: ipcc,
413 }
414 }
415
416 /// Returns CPU2 wireless firmware information (if present).
417 pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> {
418 let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table };
419
420 // Zero version indicates that CPU2 wasn't active and didn't fill the information table
421 if info.version != 0 {
422 Some(*info)
423 } else {
424 None
425 }
426 }
427
428 /// picks single [`EvtBox`] from internal event queue.
429 ///
430 /// Internal event queu is populated in IPCC_RX_IRQ handler
431 pub fn dequeue_event(&mut self) -> Option<EvtBox> {
432 HEAPLESS_EVT_QUEUE.try_recv().ok()
433 }
434
435 /// retrieves last Command Complete event and removes it from mailbox
436 pub fn pop_last_cc_evt(&mut self) -> Option<CcEvt> {
437 if LAST_CC_EVT.signaled() {
438 let cc = Some(block_on(LAST_CC_EVT.wait()));
439 LAST_CC_EVT.reset();
440
441 cc
442 } else {
443 None
444 }
445 }
446}
diff --git a/embassy-stm32/src/tl_mbox/shci.rs b/embassy-stm32/src/tl_mbox/shci.rs
deleted file mode 100644
index b19baa702..000000000
--- a/embassy-stm32/src/tl_mbox/shci.rs
+++ /dev/null
@@ -1,100 +0,0 @@
1use super::cmd::CmdPacket;
2use super::consts::TlPacketType;
3use super::{sys, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE};
4
5const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66;
6
7#[derive(Debug, Clone, Copy)]
8#[repr(C, packed)]
9pub struct ShciBleInitCmdParam {
10 /// NOT USED CURRENTLY
11 pub p_ble_buffer_address: u32,
12
13 /// Size of the Buffer allocated in pBleBufferAddress
14 pub ble_buffer_size: u32,
15
16 pub num_attr_record: u16,
17 pub num_attr_serv: u16,
18 pub attr_value_arr_size: u16,
19 pub num_of_links: u8,
20 pub extended_packet_length_enable: u8,
21 pub pr_write_list_size: u8,
22 pub mb_lock_count: u8,
23
24 pub att_mtu: u16,
25 pub slave_sca: u16,
26 pub master_sca: u8,
27 pub ls_source: u8,
28 pub max_conn_event_length: u32,
29 pub hs_startup_time: u16,
30 pub viterbi_enable: u8,
31 pub ll_only: u8,
32 pub hw_version: u8,
33}
34
35impl Default for ShciBleInitCmdParam {
36 fn default() -> Self {
37 Self {
38 p_ble_buffer_address: 0,
39 ble_buffer_size: 0,
40 num_attr_record: 68,
41 num_attr_serv: 8,
42 attr_value_arr_size: 1344,
43 num_of_links: 2,
44 extended_packet_length_enable: 1,
45 pr_write_list_size: 0x3A,
46 mb_lock_count: 0x79,
47 att_mtu: 156,
48 slave_sca: 500,
49 master_sca: 0,
50 ls_source: 1,
51 max_conn_event_length: 0xFFFFFFFF,
52 hs_startup_time: 0x148,
53 viterbi_enable: 1,
54 ll_only: 0,
55 hw_version: 0,
56 }
57 }
58}
59
60#[derive(Debug, Clone, Copy, Default)]
61#[repr(C, packed)]
62pub struct ShciHeader {
63 metadata: [u32; 3],
64}
65
66#[derive(Debug, Clone, Copy)]
67#[repr(C, packed)]
68pub struct ShciBleInitCmdPacket {
69 header: ShciHeader,
70 param: ShciBleInitCmdParam,
71}
72
73pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE;
74#[allow(dead_code)] // Not used currently but reserved
75const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE;
76
77pub fn shci_ble_init(param: ShciBleInitCmdParam) {
78 debug!("shci init");
79
80 let mut packet = ShciBleInitCmdPacket {
81 header: ShciHeader::default(),
82 param,
83 };
84
85 let packet_ptr: *mut _ = &mut packet;
86
87 unsafe {
88 let cmd_ptr: *mut CmdPacket = packet_ptr.cast();
89
90 (*cmd_ptr).cmdserial.cmd.cmd_code = SCHI_OPCODE_BLE_INIT;
91 (*cmd_ptr).cmdserial.cmd.payload_len = core::mem::size_of::<ShciBleInitCmdParam>() as u8;
92
93 let mut p_cmd_buffer = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer;
94 core::ptr::write(p_cmd_buffer, *cmd_ptr);
95
96 p_cmd_buffer.cmdserial.ty = TlPacketType::SysCmd as u8;
97
98 sys::send_cmd();
99 }
100}
diff --git a/embassy-stm32/src/tl_mbox/sys.rs b/embassy-stm32/src/tl_mbox/sys.rs
deleted file mode 100644
index c87aa440c..000000000
--- a/embassy-stm32/src/tl_mbox/sys.rs
+++ /dev/null
@@ -1,76 +0,0 @@
1use embassy_futures::block_on;
2
3use super::cmd::{CmdPacket, CmdSerial};
4use super::evt::{CcEvt, EvtBox, EvtSerial};
5use super::ipcc::Ipcc;
6use super::unsafe_linked_list::LinkedListNode;
7use super::{channels, SysTable, HEAPLESS_EVT_QUEUE, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE};
8
9pub struct Sys;
10
11impl Sys {
12 pub fn new() -> Self {
13 unsafe {
14 LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr());
15
16 TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable {
17 pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(),
18 sys_queue: SYSTEM_EVT_QUEUE.as_ptr(),
19 })
20 }
21
22 Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true);
23
24 Sys
25 }
26
27 pub fn cmd_evt_handler() -> CcEvt {
28 Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, false);
29
30 // ST's command response data structure is really convoluted.
31 //
32 // for command response events on SYS channel, the header is missing
33 // and one should:
34 // 1. interpret the content of CMD_BUFFER as CmdPacket
35 // 2. Access CmdPacket's cmdserial field and interpret its content as EvtSerial
36 // 3. Access EvtSerial's evt field (as Evt) and interpret its payload as CcEvt
37 // 4. CcEvt type is the actual SHCI response
38 // 5. profit
39 unsafe {
40 let pcmd: *const CmdPacket = (*TL_SYS_TABLE.as_ptr()).pcmd_buffer;
41
42 let a = unsafe {
43 core::slice::from_raw_parts(&pcmd as *const _ as *const u8, core::mem::size_of::<CmdPacket>())
44 };
45 debug!("shci response {:#04x}", a);
46
47 let cmd_serial: *const CmdSerial = &(*pcmd).cmdserial;
48 let evt_serial: *const EvtSerial = cmd_serial.cast();
49 let cc: *const CcEvt = (*evt_serial).evt.payload.as_ptr().cast();
50 *cc
51 }
52 }
53
54 pub fn evt_handler() {
55 unsafe {
56 let mut node_ptr = core::ptr::null_mut();
57 let node_ptr_ptr: *mut _ = &mut node_ptr;
58
59 while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) {
60 LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr);
61
62 let event = node_ptr.cast();
63 let event = EvtBox::new(event);
64
65 block_on(HEAPLESS_EVT_QUEUE.send(event));
66 }
67 }
68
69 Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL);
70 }
71}
72
73pub fn send_cmd() {
74 Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL);
75 Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true);
76}
diff --git a/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs b/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs
deleted file mode 100644
index 482e2bf5a..000000000
--- a/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs
+++ /dev/null
@@ -1,125 +0,0 @@
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
32impl LinkedListNode {
33 pub unsafe fn init_head(mut list_head: *mut LinkedListNode) {
34 (*list_head).next = list_head;
35 (*list_head).prev = list_head;
36 }
37
38 pub unsafe fn is_empty(mut list_head: *mut LinkedListNode) -> bool {
39 interrupt::free(|_| ((*list_head).next) == list_head)
40 }
41
42 pub unsafe fn insert_head(mut list_head: *mut LinkedListNode, mut node: *mut LinkedListNode) {
43 interrupt::free(|_| {
44 (*node).next = (*list_head).next;
45 (*node).prev = list_head;
46 (*list_head).next = node;
47 (*(*node).next).prev = node;
48 });
49 }
50
51 pub unsafe fn insert_tail(mut list_head: *mut LinkedListNode, mut node: *mut LinkedListNode) {
52 interrupt::free(|_| {
53 (*node).next = list_head;
54 (*node).prev = (*list_head).prev;
55 (*list_head).prev = node;
56 (*(*node).prev).next = node;
57 });
58 }
59
60 pub unsafe fn remove_node(mut node: *mut LinkedListNode) {
61 interrupt::free(|_| {
62 (*(*node).prev).next = (*node).next;
63 (*(*node).next).prev = (*node).prev;
64 });
65 }
66
67 pub unsafe fn remove_head(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
68 interrupt::free(|_| {
69 *node = (*list_head).next;
70 Self::remove_node((*list_head).next);
71 });
72 }
73
74 pub unsafe fn remove_tail(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
75 interrupt::free(|_| {
76 *node = (*list_head).prev;
77 Self::remove_node((*list_head).prev);
78 });
79 }
80
81 pub unsafe fn insert_node_after(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) {
82 interrupt::free(|_| {
83 (*node).next = (*ref_node).next;
84 (*node).prev = ref_node;
85 (*ref_node).next = node;
86 (*(*node).next).prev = node;
87 });
88 }
89
90 pub unsafe fn insert_node_before(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) {
91 interrupt::free(|_| {
92 (*node).next = ref_node;
93 (*node).prev = (*ref_node).prev;
94 (*ref_node).prev = node;
95 (*(*node).prev).next = node;
96 });
97 }
98
99 pub unsafe fn get_size(mut list_head: *mut LinkedListNode) -> usize {
100 interrupt::free(|_| {
101 let mut size = 0;
102 let mut temp: *mut LinkedListNode = core::ptr::null_mut::<LinkedListNode>();
103
104 temp = (*list_head).next;
105 while temp != list_head {
106 size += 1;
107 temp = (*temp).next
108 }
109
110 size
111 })
112 }
113
114 pub unsafe fn get_next_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
115 interrupt::free(|_| {
116 *node = (*ref_node).next;
117 });
118 }
119
120 pub unsafe fn get_prev_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
121 interrupt::free(|_| {
122 *node = (*ref_node).prev;
123 });
124 }
125}