aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32-wpan/Cargo.toml23
-rw-r--r--embassy-stm32-wpan/src/ble.rs (renamed from embassy-stm32/src/tl_mbox/ble.rs)39
-rw-r--r--embassy-stm32-wpan/src/channels.rs (renamed from embassy-stm32/src/tl_mbox/channels.rs)16
-rw-r--r--embassy-stm32-wpan/src/cmd.rs (renamed from embassy-stm32/src/tl_mbox/cmd.rs)4
-rw-r--r--embassy-stm32-wpan/src/consts.rs (renamed from embassy-stm32/src/tl_mbox/consts.rs)0
-rw-r--r--embassy-stm32-wpan/src/evt.rs (renamed from embassy-stm32/src/tl_mbox/evt.rs)14
-rw-r--r--embassy-stm32-wpan/src/fmt.rs225
-rw-r--r--embassy-stm32-wpan/src/lib.rs (renamed from embassy-stm32/src/tl_mbox/mod.rs)266
-rw-r--r--embassy-stm32-wpan/src/mm.rs (renamed from embassy-stm32/src/tl_mbox/mm.rs)18
-rw-r--r--embassy-stm32-wpan/src/rc.rs50
-rw-r--r--embassy-stm32-wpan/src/shci.rs (renamed from embassy-stm32/src/tl_mbox/shci.rs)4
-rw-r--r--embassy-stm32-wpan/src/sys.rs (renamed from embassy-stm32/src/tl_mbox/sys.rs)36
-rw-r--r--embassy-stm32-wpan/src/tables.rs175
-rw-r--r--embassy-stm32-wpan/src/unsafe_linked_list.rs (renamed from embassy-stm32/src/tl_mbox/unsafe_linked_list.rs)9
-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/hci.rs60
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_tx_rx.rs20
18 files changed, 653 insertions, 370 deletions
diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml
new file mode 100644
index 000000000..a6673d472
--- /dev/null
+++ b/embassy-stm32-wpan/Cargo.toml
@@ -0,0 +1,23 @@
1[package]
2name = "embassy-stm32-wpan"
3version = "0.1.0"
4edition = "2021"
5license = "MIT OR Apache-2.0"
6
7[dependencies]
8embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", features = ["stm32wb55rg"] }
9embassy-sync = { version = "0.2.0", path = "../embassy-sync" }
10embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true }
11embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
12embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]}
13embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
14embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
15
16defmt = { version = "0.3", optional = true }
17cortex-m = "0.7.6"
18heapless = "0.7.16"
19
20bit_field = "0.10.2"
21
22[features]
23defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"]
diff --git a/embassy-stm32/src/tl_mbox/ble.rs b/embassy-stm32-wpan/src/ble.rs
index 45bf81ef2..4546bde07 100644
--- a/embassy-stm32/src/tl_mbox/ble.rs
+++ b/embassy-stm32-wpan/src/ble.rs
@@ -1,23 +1,24 @@
1use embassy_futures::block_on; 1use core::mem::MaybeUninit;
2 2
3use super::cmd::{CmdPacket, CmdSerial}; 3use embassy_stm32::ipcc::Ipcc;
4use super::consts::TlPacketType; 4
5use super::evt::EvtBox; 5use crate::cmd::{CmdPacket, CmdSerial};
6use super::ipcc::Ipcc; 6use crate::consts::TlPacketType;
7use super::unsafe_linked_list::LinkedListNode; 7use crate::evt::EvtBox;
8use super::{ 8use crate::tables::BleTable;
9 channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, HEAPLESS_EVT_QUEUE, TL_BLE_TABLE, 9use crate::unsafe_linked_list::LinkedListNode;
10 TL_REF_TABLE, 10use crate::{
11 channels, BLE_CMD_BUFFER, CS_BUFFER, EVT_CHANNEL, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE, TL_REF_TABLE,
11}; 12};
12 13
13pub struct Ble; 14pub struct Ble;
14 15
15impl Ble { 16impl Ble {
16 pub(super) fn new() -> Self { 17 pub(super) fn enable() {
17 unsafe { 18 unsafe {
18 LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); 19 LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr());
19 20
20 TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable { 21 TL_BLE_TABLE = MaybeUninit::new(BleTable {
21 pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), 22 pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(),
22 pcs_buffer: CS_BUFFER.as_ptr().cast(), 23 pcs_buffer: CS_BUFFER.as_ptr().cast(),
23 pevt_queue: EVT_QUEUE.as_ptr().cast(), 24 pevt_queue: EVT_QUEUE.as_ptr().cast(),
@@ -26,8 +27,6 @@ impl Ble {
26 } 27 }
27 28
28 Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true); 29 Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true);
29
30 Ble
31 } 30 }
32 31
33 pub(super) fn evt_handler() { 32 pub(super) fn evt_handler() {
@@ -41,20 +40,22 @@ impl Ble {
41 let event = node_ptr.cast(); 40 let event = node_ptr.cast();
42 let event = EvtBox::new(event); 41 let event = EvtBox::new(event);
43 42
44 block_on(HEAPLESS_EVT_QUEUE.send(event)); 43 EVT_CHANNEL.try_send(event).unwrap();
45 } 44 }
46 } 45 }
47 46
48 Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL); 47 Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL);
49 } 48 }
50 49
51 pub(super) fn acl_data_handler(&self) { 50 pub(super) fn acl_data_handler() {
52 Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, false); 51 Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, false);
53 52
54 // TODO: ACL data ack to the user 53 // TODO: ACL data ack to the user
55 } 54 }
56 55
57 pub fn send_cmd(buf: &[u8]) { 56 pub fn ble_send_cmd(buf: &[u8]) {
57 debug!("writing ble cmd");
58
58 unsafe { 59 unsafe {
59 let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; 60 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: *mut CmdSerial = &mut (*pcmd_buffer).cmdserial;
@@ -70,8 +71,8 @@ impl Ble {
70 } 71 }
71 72
72 #[allow(dead_code)] // Not used currently but reserved 73 #[allow(dead_code)] // Not used currently but reserved
73 pub(super) fn send_acl_data() { 74 pub(super) fn ble_send_acl_data() {
74 let cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; 75 let mut cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer };
75 76
76 cmd_packet.acl_data_serial.ty = TlPacketType::AclData as u8; 77 cmd_packet.acl_data_serial.ty = TlPacketType::AclData as u8;
77 78
diff --git a/embassy-stm32/src/tl_mbox/channels.rs b/embassy-stm32-wpan/src/channels.rs
index 25a065ba4..9a2be1cfa 100644
--- a/embassy-stm32/src/tl_mbox/channels.rs
+++ b/embassy-stm32-wpan/src/channels.rs
@@ -50,36 +50,30 @@
50//! 50//!
51 51
52pub mod cpu1 { 52pub mod cpu1 {
53 use crate::tl_mbox::ipcc::IpccChannel; 53 use embassy_stm32::ipcc::IpccChannel;
54 54
55 // Not used currently but reserved
56 pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1; 55 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; 56 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; 57 pub const IPCC_THREAD_OT_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3;
61 #[allow(dead_code)] // Not used currently but reserved 58 #[allow(dead_code)] // Not used currently but reserved
62 pub const IPCC_ZIGBEE_CMD_APPLI_CHANNEL: IpccChannel = IpccChannel::Channel3; 59 pub const IPCC_ZIGBEE_CMD_APPLI_CHANNEL: IpccChannel = IpccChannel::Channel3;
63 #[allow(dead_code)] // Not used currently but reserved 60 #[allow(dead_code)] // Not used currently but reserved
64 pub const IPCC_MAC_802_15_4_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; 61 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 62 #[allow(dead_code)] // Not used currently but reserved
63 pub const IPCC_MM_RELEASE_BUFFER_CHANNEL: IpccChannel = IpccChannel::Channel4;
68 pub const IPCC_THREAD_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; 64 pub const IPCC_THREAD_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5;
69 #[allow(dead_code)] // Not used currently but reserved 65 #[allow(dead_code)] // Not used currently but reserved
70 pub const IPCC_LLDTESTS_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; 66 pub const IPCC_LLDTESTS_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5;
71 #[allow(dead_code)] // Not used currently but reserved 67 #[allow(dead_code)] // Not used currently but reserved
72 pub const IPCC_BLE_LLD_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; 68 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; 69 pub const IPCC_HCI_ACL_DATA_CHANNEL: IpccChannel = IpccChannel::Channel6;
75} 70}
76 71
77pub mod cpu2 { 72pub mod cpu2 {
78 use crate::tl_mbox::ipcc::IpccChannel; 73 use embassy_stm32::ipcc::IpccChannel;
79 74
80 pub const IPCC_BLE_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel1; 75 pub const IPCC_BLE_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel1;
81 pub const IPCC_SYSTEM_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel2; 76 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; 77 pub const IPCC_THREAD_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3;
84 #[allow(dead_code)] // Not used currently but reserved 78 #[allow(dead_code)] // Not used currently but reserved
85 pub const IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3; 79 pub const IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3;
@@ -88,10 +82,8 @@ pub mod cpu2 {
88 #[allow(dead_code)] // Not used currently but reserved 82 #[allow(dead_code)] // Not used currently but reserved
89 pub const IPCC_LDDTESTS_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; 83 pub const IPCC_LDDTESTS_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3;
90 #[allow(dead_code)] // Not used currently but reserved 84 #[allow(dead_code)] // Not used currently but reserved
91 pub const IPCC_BLE_LLD_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; 85 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; 86 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; 87 pub const IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel5;
96 #[allow(dead_code)] // Not used currently but reserved 88 #[allow(dead_code)] // Not used currently but reserved
97 pub const IPCC_LLDTESTS_CLI_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5; 89 pub const IPCC_LLDTESTS_CLI_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5;
diff --git a/embassy-stm32/src/tl_mbox/cmd.rs b/embassy-stm32-wpan/src/cmd.rs
index 781aa669d..1f7dae7f7 100644
--- a/embassy-stm32/src/tl_mbox/cmd.rs
+++ b/embassy-stm32-wpan/src/cmd.rs
@@ -1,5 +1,5 @@
1use crate::tl_mbox::evt::{EvtPacket, EvtSerial}; 1use crate::evt::{EvtPacket, EvtSerial};
2use crate::tl_mbox::{PacketHeader, TL_EVT_HEADER_SIZE}; 2use crate::{PacketHeader, TL_EVT_HEADER_SIZE};
3 3
4#[derive(Copy, Clone)] 4#[derive(Copy, Clone)]
5#[repr(C, packed)] 5#[repr(C, packed)]
diff --git a/embassy-stm32/src/tl_mbox/consts.rs b/embassy-stm32-wpan/src/consts.rs
index caf26c06b..caf26c06b 100644
--- a/embassy-stm32/src/tl_mbox/consts.rs
+++ b/embassy-stm32-wpan/src/consts.rs
diff --git a/embassy-stm32/src/tl_mbox/evt.rs b/embassy-stm32-wpan/src/evt.rs
index 77ce7b4ca..b53fe506e 100644
--- a/embassy-stm32/src/tl_mbox/evt.rs
+++ b/embassy-stm32-wpan/src/evt.rs
@@ -2,13 +2,13 @@ use core::mem::MaybeUninit;
2 2
3use super::cmd::{AclDataPacket, AclDataSerial}; 3use super::cmd::{AclDataPacket, AclDataSerial};
4use super::consts::TlPacketType; 4use super::consts::TlPacketType;
5use super::mm::MemoryManager;
6use super::{PacketHeader, TL_EVT_HEADER_SIZE}; 5use super::{PacketHeader, TL_EVT_HEADER_SIZE};
6use crate::mm;
7 7
8/** 8/**
9 * The payload of `Evt` for a command status event 9 * The payload of `Evt` for a command status event
10 */ 10 */
11#[derive(Debug, Copy, Clone)] 11#[derive(Copy, Clone)]
12#[repr(C, packed)] 12#[repr(C, packed)]
13pub struct CsEvt { 13pub struct CsEvt {
14 pub status: u8, 14 pub status: u8,
@@ -19,7 +19,7 @@ pub struct CsEvt {
19/** 19/**
20 * The payload of `Evt` for a command complete event 20 * The payload of `Evt` for a command complete event
21 */ 21 */
22#[derive(Debug, Copy, Clone, Default)] 22#[derive(Copy, Clone, Default)]
23#[repr(C, packed)] 23#[repr(C, packed)]
24pub struct CcEvt { 24pub struct CcEvt {
25 pub num_cmd: u8, 25 pub num_cmd: u8,
@@ -41,14 +41,14 @@ impl CcEvt {
41 } 41 }
42} 42}
43 43
44#[derive(Debug, Copy, Clone, Default)] 44#[derive(Copy, Clone, Default)]
45#[repr(C, packed)] 45#[repr(C, packed)]
46pub struct AsynchEvt { 46pub struct AsynchEvt {
47 sub_evt_code: u16, 47 sub_evt_code: u16,
48 payload: [u8; 1], 48 payload: [u8; 1],
49} 49}
50 50
51#[derive(Debug, Copy, Clone, Default)] 51#[derive(Copy, Clone, Default)]
52#[repr(C, packed)] 52#[repr(C, packed)]
53pub struct Evt { 53pub struct Evt {
54 pub evt_code: u8, 54 pub evt_code: u8,
@@ -56,7 +56,7 @@ pub struct Evt {
56 pub payload: [u8; 1], 56 pub payload: [u8; 1],
57} 57}
58 58
59#[derive(Debug, Copy, Clone, Default)] 59#[derive(Copy, Clone, Default)]
60#[repr(C, packed)] 60#[repr(C, packed)]
61pub struct EvtSerial { 61pub struct EvtSerial {
62 pub kind: u8, 62 pub kind: u8,
@@ -171,6 +171,6 @@ impl EvtBox {
171 171
172impl Drop for EvtBox { 172impl Drop for EvtBox {
173 fn drop(&mut self) { 173 fn drop(&mut self) {
174 MemoryManager::evt_drop(self.ptr); 174 mm::MemoryManager::evt_drop(self.ptr);
175 } 175 }
176} 176}
diff --git a/embassy-stm32-wpan/src/fmt.rs b/embassy-stm32-wpan/src/fmt.rs
new file mode 100644
index 000000000..066970813
--- /dev/null
+++ b/embassy-stm32-wpan/src/fmt.rs
@@ -0,0 +1,225 @@
1#![macro_use]
2#![allow(unused_macros)]
3
4#[cfg(all(feature = "defmt", feature = "log"))]
5compile_error!("You may not enable both `defmt` and `log` features.");
6
7macro_rules! assert {
8 ($($x:tt)*) => {
9 {
10 #[cfg(not(feature = "defmt"))]
11 ::core::assert!($($x)*);
12 #[cfg(feature = "defmt")]
13 ::defmt::assert!($($x)*);
14 }
15 };
16}
17
18macro_rules! assert_eq {
19 ($($x:tt)*) => {
20 {
21 #[cfg(not(feature = "defmt"))]
22 ::core::assert_eq!($($x)*);
23 #[cfg(feature = "defmt")]
24 ::defmt::assert_eq!($($x)*);
25 }
26 };
27}
28
29macro_rules! assert_ne {
30 ($($x:tt)*) => {
31 {
32 #[cfg(not(feature = "defmt"))]
33 ::core::assert_ne!($($x)*);
34 #[cfg(feature = "defmt")]
35 ::defmt::assert_ne!($($x)*);
36 }
37 };
38}
39
40macro_rules! debug_assert {
41 ($($x:tt)*) => {
42 {
43 #[cfg(not(feature = "defmt"))]
44 ::core::debug_assert!($($x)*);
45 #[cfg(feature = "defmt")]
46 ::defmt::debug_assert!($($x)*);
47 }
48 };
49}
50
51macro_rules! debug_assert_eq {
52 ($($x:tt)*) => {
53 {
54 #[cfg(not(feature = "defmt"))]
55 ::core::debug_assert_eq!($($x)*);
56 #[cfg(feature = "defmt")]
57 ::defmt::debug_assert_eq!($($x)*);
58 }
59 };
60}
61
62macro_rules! debug_assert_ne {
63 ($($x:tt)*) => {
64 {
65 #[cfg(not(feature = "defmt"))]
66 ::core::debug_assert_ne!($($x)*);
67 #[cfg(feature = "defmt")]
68 ::defmt::debug_assert_ne!($($x)*);
69 }
70 };
71}
72
73macro_rules! todo {
74 ($($x:tt)*) => {
75 {
76 #[cfg(not(feature = "defmt"))]
77 ::core::todo!($($x)*);
78 #[cfg(feature = "defmt")]
79 ::defmt::todo!($($x)*);
80 }
81 };
82}
83
84macro_rules! unreachable {
85 ($($x:tt)*) => {
86 {
87 #[cfg(not(feature = "defmt"))]
88 ::core::unreachable!($($x)*);
89 #[cfg(feature = "defmt")]
90 ::defmt::unreachable!($($x)*);
91 }
92 };
93}
94
95macro_rules! panic {
96 ($($x:tt)*) => {
97 {
98 #[cfg(not(feature = "defmt"))]
99 ::core::panic!($($x)*);
100 #[cfg(feature = "defmt")]
101 ::defmt::panic!($($x)*);
102 }
103 };
104}
105
106macro_rules! trace {
107 ($s:literal $(, $x:expr)* $(,)?) => {
108 {
109 #[cfg(feature = "log")]
110 ::log::trace!($s $(, $x)*);
111 #[cfg(feature = "defmt")]
112 ::defmt::trace!($s $(, $x)*);
113 #[cfg(not(any(feature = "log", feature="defmt")))]
114 let _ = ($( & $x ),*);
115 }
116 };
117}
118
119macro_rules! debug {
120 ($s:literal $(, $x:expr)* $(,)?) => {
121 {
122 #[cfg(feature = "log")]
123 ::log::debug!($s $(, $x)*);
124 #[cfg(feature = "defmt")]
125 ::defmt::debug!($s $(, $x)*);
126 #[cfg(not(any(feature = "log", feature="defmt")))]
127 let _ = ($( & $x ),*);
128 }
129 };
130}
131
132macro_rules! info {
133 ($s:literal $(, $x:expr)* $(,)?) => {
134 {
135 #[cfg(feature = "log")]
136 ::log::info!($s $(, $x)*);
137 #[cfg(feature = "defmt")]
138 ::defmt::info!($s $(, $x)*);
139 #[cfg(not(any(feature = "log", feature="defmt")))]
140 let _ = ($( & $x ),*);
141 }
142 };
143}
144
145macro_rules! warn {
146 ($s:literal $(, $x:expr)* $(,)?) => {
147 {
148 #[cfg(feature = "log")]
149 ::log::warn!($s $(, $x)*);
150 #[cfg(feature = "defmt")]
151 ::defmt::warn!($s $(, $x)*);
152 #[cfg(not(any(feature = "log", feature="defmt")))]
153 let _ = ($( & $x ),*);
154 }
155 };
156}
157
158macro_rules! error {
159 ($s:literal $(, $x:expr)* $(,)?) => {
160 {
161 #[cfg(feature = "log")]
162 ::log::error!($s $(, $x)*);
163 #[cfg(feature = "defmt")]
164 ::defmt::error!($s $(, $x)*);
165 #[cfg(not(any(feature = "log", feature="defmt")))]
166 let _ = ($( & $x ),*);
167 }
168 };
169}
170
171#[cfg(feature = "defmt")]
172macro_rules! unwrap {
173 ($($x:tt)*) => {
174 ::defmt::unwrap!($($x)*)
175 };
176}
177
178#[cfg(not(feature = "defmt"))]
179macro_rules! unwrap {
180 ($arg:expr) => {
181 match $crate::fmt::Try::into_result($arg) {
182 ::core::result::Result::Ok(t) => t,
183 ::core::result::Result::Err(e) => {
184 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
185 }
186 }
187 };
188 ($arg:expr, $($msg:expr),+ $(,)? ) => {
189 match $crate::fmt::Try::into_result($arg) {
190 ::core::result::Result::Ok(t) => t,
191 ::core::result::Result::Err(e) => {
192 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
193 }
194 }
195 }
196}
197
198#[derive(Debug, Copy, Clone, Eq, PartialEq)]
199pub struct NoneError;
200
201pub trait Try {
202 type Ok;
203 type Error;
204 fn into_result(self) -> Result<Self::Ok, Self::Error>;
205}
206
207impl<T> Try for Option<T> {
208 type Ok = T;
209 type Error = NoneError;
210
211 #[inline]
212 fn into_result(self) -> Result<T, NoneError> {
213 self.ok_or(NoneError)
214 }
215}
216
217impl<T, E> Try for Result<T, E> {
218 type Ok = T;
219 type Error = E;
220
221 #[inline]
222 fn into_result(self) -> Self {
223 self
224 }
225}
diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32-wpan/src/lib.rs
index 21a954417..b3206428e 100644
--- a/embassy-stm32/src/tl_mbox/mod.rs
+++ b/embassy-stm32-wpan/src/lib.rs
@@ -1,30 +1,37 @@
1#![no_std]
2
3// This must go FIRST so that all the other modules see its macros.
4pub mod fmt;
5
1use core::mem::MaybeUninit; 6use core::mem::MaybeUninit;
2 7
3use bit_field::BitField; 8use cmd::CmdPacket;
4use embassy_cortex_m::interrupt::Interrupt; 9use embassy_cortex_m::interrupt::Interrupt;
5use embassy_futures::block_on; 10use embassy_futures::block_on;
6use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 11use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
12use embassy_stm32::interrupt;
13use embassy_stm32::ipcc::{Config, Ipcc};
14use embassy_stm32::peripherals::IPCC;
7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 15use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
8use embassy_sync::channel::Channel; 16use embassy_sync::channel::Channel;
9use embassy_sync::signal::Signal; 17use embassy_sync::signal::Signal;
10 18use evt::{CcEvt, EvtBox};
11use self::cmd::{AclDataPacket, CmdPacket}; 19use tables::{
12use self::evt::{CcEvt, EvtBox}; 20 BleTable, DeviceInfoTable, Mac802_15_4Table, MemManagerTable, RefTable, SysTable, ThreadTable, TracesTable,
13use self::ipcc::{Config, Ipcc}; 21 WirelessFwInfoTable,
14use self::unsafe_linked_list::LinkedListNode; 22};
15use crate::interrupt; 23use unsafe_linked_list::LinkedListNode;
16use crate::peripherals::IPCC;
17 24
18pub mod ble; 25pub mod ble;
19pub mod channels; 26pub mod channels;
20pub mod cmd; 27pub mod cmd;
21pub mod consts; 28pub mod consts;
22pub mod evt; 29pub mod evt;
23pub mod hci;
24pub mod ipcc;
25pub mod mm; 30pub mod mm;
31pub mod rc;
26pub mod shci; 32pub mod shci;
27pub mod sys; 33pub mod sys;
34pub mod tables;
28pub mod unsafe_linked_list; 35pub mod unsafe_linked_list;
29 36
30/// Interrupt handler. 37/// Interrupt handler.
@@ -32,16 +39,12 @@ pub struct ReceiveInterruptHandler {}
32 39
33impl interrupt::Handler<interrupt::IPCC_C1_RX> for ReceiveInterruptHandler { 40impl interrupt::Handler<interrupt::IPCC_C1_RX> for ReceiveInterruptHandler {
34 unsafe fn on_interrupt() { 41 unsafe fn on_interrupt() {
35 debug!("ipcc rx interrupt");
36
37 if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { 42 if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) {
38 debug!("sys evt"); 43 debug!("RX SYS evt");
39 sys::Sys::evt_handler(); 44 sys::Sys::evt_handler();
40 } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) { 45 } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) {
41 debug!("ble evt"); 46 debug!("RX BLE evt");
42 ble::Ble::evt_handler(); 47 ble::Ble::evt_handler();
43 } else {
44 todo!()
45 } 48 }
46 49
47 STATE.signal(()); 50 STATE.signal(());
@@ -52,198 +55,23 @@ pub struct TransmitInterruptHandler {}
52 55
53impl interrupt::Handler<interrupt::IPCC_C1_TX> for TransmitInterruptHandler { 56impl interrupt::Handler<interrupt::IPCC_C1_TX> for TransmitInterruptHandler {
54 unsafe fn on_interrupt() { 57 unsafe fn on_interrupt() {
55 debug!("ipcc tx interrupt");
56
57 if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { 58 if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) {
58 debug!("sys cmd rsp"); 59 debug!("TX SYS cmd rsp");
59 // TODO: handle this case
60 let cc = sys::Sys::cmd_evt_handler(); 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 61
64 LAST_CC_EVT.signal(cc); 62 LAST_CC_EVT.signal(cc);
65 } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) { 63 } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) {
66 debug!("mm"); 64 debug!("TX MM release");
67 mm::MemoryManager::free_buf_handler(); 65 mm::MemoryManager::free_buf_handler();
68 } else { 66 } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL) {
69 todo!() 67 debug!("TX HCI acl");
68 ble::Ble::acl_data_handler();
70 } 69 }
71 70
72 STATE.signal(()); 71 STATE.signal(());
73 } 72 }
74} 73}
75 74
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"] 75#[link_section = "TL_REF_TABLE"]
248pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit(); 76pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit();
249 77
@@ -338,25 +166,21 @@ static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
338// fuck these "magic" numbers from ST ---v---v 166// fuck these "magic" numbers from ST ---v---v
339static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); 167static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit();
340 168
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 169/// current event that is produced during IPCC IRQ handler execution
346/// on SYS channel 170/// on SYS channel
171static EVT_CHANNEL: Channel<CriticalSectionRawMutex, EvtBox, 32> = Channel::new();
172
347/// last received Command Complete event 173/// last received Command Complete event
348static LAST_CC_EVT: Signal<CriticalSectionRawMutex, CcEvt> = Signal::new(); 174static LAST_CC_EVT: Signal<CriticalSectionRawMutex, CcEvt> = Signal::new();
349 175
350pub struct TlMbox<'d> { 176static STATE: Signal<CriticalSectionRawMutex, ()> = Signal::new();
351 sys: sys::Sys,
352 ble: ble::Ble,
353 _mm: mm::MemoryManager,
354 177
178pub struct TlMbox<'d> {
355 _ipcc: PeripheralRef<'d, IPCC>, 179 _ipcc: PeripheralRef<'d, IPCC>,
356} 180}
357 181
358impl<'d> TlMbox<'d> { 182impl<'d> TlMbox<'d> {
359 pub fn new( 183 pub fn init(
360 ipcc: impl Peripheral<P = IPCC> + 'd, 184 ipcc: impl Peripheral<P = IPCC> + 'd,
361 _irqs: impl interrupt::Binding<interrupt::IPCC_C1_RX, ReceiveInterruptHandler> 185 _irqs: impl interrupt::Binding<interrupt::IPCC_C1_RX, ReceiveInterruptHandler>
362 + interrupt::Binding<interrupt::IPCC_C1_TX, TransmitInterruptHandler>, 186 + interrupt::Binding<interrupt::IPCC_C1_TX, TransmitInterruptHandler>,
@@ -365,7 +189,7 @@ impl<'d> TlMbox<'d> {
365 into_ref!(ipcc); 189 into_ref!(ipcc);
366 190
367 unsafe { 191 unsafe {
368 TL_REF_TABLE.as_mut_ptr().write_volatile(RefTable { 192 TL_REF_TABLE = MaybeUninit::new(RefTable {
369 device_info_table: TL_DEVICE_INFO_TABLE.as_mut_ptr(), 193 device_info_table: TL_DEVICE_INFO_TABLE.as_mut_ptr(),
370 ble_table: TL_BLE_TABLE.as_ptr(), 194 ble_table: TL_BLE_TABLE.as_ptr(),
371 thread_table: TL_THREAD_TABLE.as_ptr(), 195 thread_table: TL_THREAD_TABLE.as_ptr(),
@@ -394,23 +218,20 @@ impl<'d> TlMbox<'d> {
394 218
395 Ipcc::enable(config); 219 Ipcc::enable(config);
396 220
397 let sys = sys::Sys::new(); 221 sys::Sys::enable();
398 let ble = ble::Ble::new(); 222 ble::Ble::enable();
399 let mm = mm::MemoryManager::new(); 223 mm::MemoryManager::enable();
400 224
401 // enable interrupts 225 // enable interrupts
402 crate::interrupt::IPCC_C1_RX::unpend(); 226 interrupt::IPCC_C1_RX::unpend();
403 crate::interrupt::IPCC_C1_TX::unpend(); 227 interrupt::IPCC_C1_TX::unpend();
404 228
405 unsafe { crate::interrupt::IPCC_C1_RX::enable() }; 229 unsafe { interrupt::IPCC_C1_RX::enable() };
406 unsafe { crate::interrupt::IPCC_C1_TX::enable() }; 230 unsafe { interrupt::IPCC_C1_TX::enable() };
407 231
408 Self { 232 STATE.reset();
409 sys, 233
410 ble, 234 Self { _ipcc: ipcc }
411 _mm: mm,
412 _ipcc: ipcc,
413 }
414 } 235 }
415 236
416 /// Returns CPU2 wireless firmware information (if present). 237 /// Returns CPU2 wireless firmware information (if present).
@@ -429,16 +250,15 @@ impl<'d> TlMbox<'d> {
429 /// 250 ///
430 /// Internal event queu is populated in IPCC_RX_IRQ handler 251 /// Internal event queu is populated in IPCC_RX_IRQ handler
431 pub fn dequeue_event(&mut self) -> Option<EvtBox> { 252 pub fn dequeue_event(&mut self) -> Option<EvtBox> {
432 HEAPLESS_EVT_QUEUE.try_recv().ok() 253 EVT_CHANNEL.try_recv().ok()
433 } 254 }
434 255
435 /// retrieves last Command Complete event and removes it from mailbox 256 /// retrieves last Command Complete event and removes it from mailbox
436 pub fn pop_last_cc_evt(&mut self) -> Option<CcEvt> { 257 pub fn pop_last_cc_evt(&mut self) -> Option<CcEvt> {
437 if LAST_CC_EVT.signaled() { 258 if LAST_CC_EVT.signaled() {
438 let cc = Some(block_on(LAST_CC_EVT.wait())); 259 let cc = block_on(LAST_CC_EVT.wait());
439 LAST_CC_EVT.reset(); 260 LAST_CC_EVT.reset();
440 261 Some(cc)
441 cc
442 } else { 262 } else {
443 None 263 None
444 } 264 }
diff --git a/embassy-stm32/src/tl_mbox/mm.rs b/embassy-stm32-wpan/src/mm.rs
index a40438499..ed13b0dbf 100644
--- a/embassy-stm32/src/tl_mbox/mm.rs
+++ b/embassy-stm32-wpan/src/mm.rs
@@ -2,18 +2,20 @@
2 2
3use core::mem::MaybeUninit; 3use core::mem::MaybeUninit;
4 4
5use super::evt::EvtPacket; 5use embassy_stm32::ipcc::Ipcc;
6use super::ipcc::Ipcc; 6
7use super::unsafe_linked_list::LinkedListNode; 7use crate::evt::EvtPacket;
8use super::{ 8use crate::tables::MemManagerTable;
9 channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, 9use crate::unsafe_linked_list::LinkedListNode;
10 SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, TL_REF_TABLE, 10use crate::{
11 channels, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF,
12 TL_MEM_MANAGER_TABLE, TL_REF_TABLE,
11}; 13};
12 14
13pub(super) struct MemoryManager; 15pub(super) struct MemoryManager;
14 16
15impl MemoryManager { 17impl MemoryManager {
16 pub fn new() -> Self { 18 pub fn enable() {
17 unsafe { 19 unsafe {
18 LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); 20 LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr());
19 LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); 21 LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr());
@@ -28,8 +30,6 @@ impl MemoryManager {
28 tracespoolsize: 0, 30 tracespoolsize: 0,
29 }); 31 });
30 } 32 }
31
32 MemoryManager
33 } 33 }
34 34
35 pub fn evt_drop(evt: *mut EvtPacket) { 35 pub fn evt_drop(evt: *mut EvtPacket) {
diff --git a/embassy-stm32-wpan/src/rc.rs b/embassy-stm32-wpan/src/rc.rs
new file mode 100644
index 000000000..aae2265ed
--- /dev/null
+++ b/embassy-stm32-wpan/src/rc.rs
@@ -0,0 +1,50 @@
1use crate::ble::Ble;
2use crate::consts::TlPacketType;
3use crate::{shci, TlMbox, STATE};
4
5pub struct RadioCoprocessor<'d> {
6 mbox: TlMbox<'d>,
7 rx_buf: [u8; 500],
8}
9
10impl<'d> RadioCoprocessor<'d> {
11 pub fn new(mbox: TlMbox<'d>) -> Self {
12 Self {
13 mbox,
14 rx_buf: [0u8; 500],
15 }
16 }
17
18 pub fn write(&self, buf: &[u8]) {
19 let cmd_code = buf[0];
20 let cmd = TlPacketType::try_from(cmd_code).unwrap();
21
22 match &cmd {
23 TlPacketType::BleCmd => Ble::ble_send_cmd(buf),
24 _ => todo!(),
25 }
26 }
27
28 pub async fn read(&mut self) -> &[u8] {
29 loop {
30 STATE.wait().await;
31
32 while let Some(evt) = self.mbox.dequeue_event() {
33 let event = evt.evt();
34
35 evt.write(&mut self.rx_buf).unwrap();
36
37 if event.kind() == 18 {
38 shci::shci_ble_init(Default::default());
39 self.rx_buf[0] = 0x04;
40 }
41 }
42
43 if self.mbox.pop_last_cc_evt().is_some() {
44 continue;
45 }
46
47 return &self.rx_buf;
48 }
49 }
50}
diff --git a/embassy-stm32/src/tl_mbox/shci.rs b/embassy-stm32-wpan/src/shci.rs
index b19baa702..4f4d08886 100644
--- a/embassy-stm32/src/tl_mbox/shci.rs
+++ b/embassy-stm32-wpan/src/shci.rs
@@ -75,7 +75,7 @@ pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE
75const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; 75const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE;
76 76
77pub fn shci_ble_init(param: ShciBleInitCmdParam) { 77pub fn shci_ble_init(param: ShciBleInitCmdParam) {
78 debug!("shci init"); 78 debug!("sending SHCI");
79 79
80 let mut packet = ShciBleInitCmdPacket { 80 let mut packet = ShciBleInitCmdPacket {
81 header: ShciHeader::default(), 81 header: ShciHeader::default(),
@@ -95,6 +95,6 @@ pub fn shci_ble_init(param: ShciBleInitCmdParam) {
95 95
96 p_cmd_buffer.cmdserial.ty = TlPacketType::SysCmd as u8; 96 p_cmd_buffer.cmdserial.ty = TlPacketType::SysCmd as u8;
97 97
98 sys::send_cmd(); 98 sys::Sys::send_cmd();
99 } 99 }
100} 100}
diff --git a/embassy-stm32/src/tl_mbox/sys.rs b/embassy-stm32-wpan/src/sys.rs
index c87aa440c..a19d12d27 100644
--- a/embassy-stm32/src/tl_mbox/sys.rs
+++ b/embassy-stm32-wpan/src/sys.rs
@@ -1,27 +1,27 @@
1use embassy_futures::block_on; 1use core::mem::MaybeUninit;
2 2
3use super::cmd::{CmdPacket, CmdSerial}; 3use embassy_stm32::ipcc::Ipcc;
4use super::evt::{CcEvt, EvtBox, EvtSerial}; 4
5use super::ipcc::Ipcc; 5use crate::cmd::{CmdPacket, CmdSerial};
6use super::unsafe_linked_list::LinkedListNode; 6use crate::evt::{CcEvt, EvtBox, EvtSerial};
7use super::{channels, SysTable, HEAPLESS_EVT_QUEUE, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; 7use crate::tables::SysTable;
8use crate::unsafe_linked_list::LinkedListNode;
9use crate::{channels, EVT_CHANNEL, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE};
8 10
9pub struct Sys; 11pub struct Sys;
10 12
11impl Sys { 13impl Sys {
12 pub fn new() -> Self { 14 pub fn enable() {
13 unsafe { 15 unsafe {
14 LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); 16 LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr());
15 17
16 TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { 18 TL_SYS_TABLE = MaybeUninit::new(SysTable {
17 pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), 19 pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(),
18 sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), 20 sys_queue: SYSTEM_EVT_QUEUE.as_ptr(),
19 }) 21 })
20 } 22 }
21 23
22 Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true); 24 Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true);
23
24 Sys
25 } 25 }
26 26
27 pub fn cmd_evt_handler() -> CcEvt { 27 pub fn cmd_evt_handler() -> CcEvt {
@@ -38,12 +38,6 @@ impl Sys {
38 // 5. profit 38 // 5. profit
39 unsafe { 39 unsafe {
40 let pcmd: *const CmdPacket = (*TL_SYS_TABLE.as_ptr()).pcmd_buffer; 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; 41 let cmd_serial: *const CmdSerial = &(*pcmd).cmdserial;
48 let evt_serial: *const EvtSerial = cmd_serial.cast(); 42 let evt_serial: *const EvtSerial = cmd_serial.cast();
49 let cc: *const CcEvt = (*evt_serial).evt.payload.as_ptr().cast(); 43 let cc: *const CcEvt = (*evt_serial).evt.payload.as_ptr().cast();
@@ -62,15 +56,15 @@ impl Sys {
62 let event = node_ptr.cast(); 56 let event = node_ptr.cast();
63 let event = EvtBox::new(event); 57 let event = EvtBox::new(event);
64 58
65 block_on(HEAPLESS_EVT_QUEUE.send(event)); 59 EVT_CHANNEL.try_send(event).unwrap();
66 } 60 }
67 } 61 }
68 62
69 Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); 63 Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL);
70 } 64 }
71}
72 65
73pub fn send_cmd() { 66 pub fn send_cmd() {
74 Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); 67 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); 68 Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true);
69 }
76} 70}
diff --git a/embassy-stm32-wpan/src/tables.rs b/embassy-stm32-wpan/src/tables.rs
new file mode 100644
index 000000000..151216958
--- /dev/null
+++ b/embassy-stm32-wpan/src/tables.rs
@@ -0,0 +1,175 @@
1use bit_field::BitField;
2
3use crate::cmd::{AclDataPacket, CmdPacket};
4use crate::unsafe_linked_list::LinkedListNode;
5
6#[derive(Debug, Copy, Clone)]
7#[repr(C, packed)]
8pub struct SafeBootInfoTable {
9 version: u32,
10}
11
12#[derive(Debug, Copy, Clone)]
13#[repr(C, packed)]
14pub struct RssInfoTable {
15 pub version: u32,
16 pub memory_size: u32,
17 pub rss_info: u32,
18}
19
20/**
21 * Version
22 * [0:3] = Build - 0: Untracked - 15:Released - x: Tracked version
23 * [4:7] = branch - 0: Mass Market - x: ...
24 * [8:15] = Subversion
25 * [16:23] = Version minor
26 * [24:31] = Version major
27 *
28 * Memory Size
29 * [0:7] = Flash ( Number of 4k sector)
30 * [8:15] = Reserved ( Shall be set to 0 - may be used as flash extension )
31 * [16:23] = SRAM2b ( Number of 1k sector)
32 * [24:31] = SRAM2a ( Number of 1k sector)
33 */
34#[derive(Debug, Copy, Clone)]
35#[repr(C, packed)]
36pub struct WirelessFwInfoTable {
37 pub version: u32,
38 pub memory_size: u32,
39 pub thread_info: u32,
40 pub ble_info: u32,
41}
42
43impl WirelessFwInfoTable {
44 pub fn version_major(&self) -> u8 {
45 let version = self.version;
46 (version.get_bits(24..31) & 0xff) as u8
47 }
48
49 pub fn version_minor(&self) -> u8 {
50 let version = self.version;
51 (version.clone().get_bits(16..23) & 0xff) as u8
52 }
53
54 pub fn subversion(&self) -> u8 {
55 let version = self.version;
56 (version.clone().get_bits(8..15) & 0xff) as u8
57 }
58
59 /// Size of FLASH, expressed in number of 4K sectors.
60 pub fn flash_size(&self) -> u8 {
61 let memory_size = self.memory_size;
62 (memory_size.clone().get_bits(0..7) & 0xff) as u8
63 }
64
65 /// Size of SRAM2a, expressed in number of 1K sectors.
66 pub fn sram2a_size(&self) -> u8 {
67 let memory_size = self.memory_size;
68 (memory_size.clone().get_bits(24..31) & 0xff) as u8
69 }
70
71 /// Size of SRAM2b, expressed in number of 1K sectors.
72 pub fn sram2b_size(&self) -> u8 {
73 let memory_size = self.memory_size;
74 (memory_size.clone().get_bits(16..23) & 0xff) as u8
75 }
76}
77
78#[derive(Debug, Clone)]
79#[repr(C, align(4))]
80pub struct DeviceInfoTable {
81 pub safe_boot_info_table: SafeBootInfoTable,
82 pub rss_info_table: RssInfoTable,
83 pub wireless_fw_info_table: WirelessFwInfoTable,
84}
85
86#[derive(Debug)]
87#[repr(C, align(4))]
88pub struct BleTable {
89 pub pcmd_buffer: *mut CmdPacket,
90 pub pcs_buffer: *const u8,
91 pub pevt_queue: *const u8,
92 pub phci_acl_data_buffer: *mut AclDataPacket,
93}
94
95#[derive(Debug)]
96#[repr(C, align(4))]
97pub struct ThreadTable {
98 pub nostack_buffer: *const u8,
99 pub clicmdrsp_buffer: *const u8,
100 pub otcmdrsp_buffer: *const u8,
101}
102
103// TODO: use later
104#[derive(Debug)]
105#[repr(C, align(4))]
106pub struct LldTestsTable {
107 pub clicmdrsp_buffer: *const u8,
108 pub m0cmd_buffer: *const u8,
109}
110
111// TODO: use later
112#[derive(Debug)]
113#[repr(C, align(4))]
114pub struct BleLldTable {
115 pub cmdrsp_buffer: *const u8,
116 pub m0cmd_buffer: *const u8,
117}
118
119// TODO: use later
120#[derive(Debug)]
121#[repr(C, align(4))]
122pub struct ZigbeeTable {
123 pub notif_m0_to_m4_buffer: *const u8,
124 pub appli_cmd_m4_to_m0_bufer: *const u8,
125 pub request_m0_to_m4_buffer: *const u8,
126}
127
128#[derive(Debug)]
129#[repr(C, align(4))]
130pub struct SysTable {
131 pub pcmd_buffer: *mut CmdPacket,
132 pub sys_queue: *const LinkedListNode,
133}
134
135#[derive(Debug)]
136#[repr(C, align(4))]
137pub struct MemManagerTable {
138 pub spare_ble_buffer: *const u8,
139 pub spare_sys_buffer: *const u8,
140
141 pub blepool: *const u8,
142 pub blepoolsize: u32,
143
144 pub pevt_free_buffer_queue: *mut LinkedListNode,
145
146 pub traces_evt_pool: *const u8,
147 pub tracespoolsize: u32,
148}
149
150#[derive(Debug)]
151#[repr(C, align(4))]
152pub struct TracesTable {
153 pub traces_queue: *const u8,
154}
155
156#[derive(Debug)]
157#[repr(C, align(4))]
158pub struct Mac802_15_4Table {
159 pub p_cmdrsp_buffer: *const u8,
160 pub p_notack_buffer: *const u8,
161 pub evt_queue: *const u8,
162}
163
164/// Reference table. Contains pointers to all other tables.
165#[derive(Debug, Copy, Clone)]
166#[repr(C)]
167pub struct RefTable {
168 pub device_info_table: *const DeviceInfoTable,
169 pub ble_table: *const BleTable,
170 pub thread_table: *const ThreadTable,
171 pub sys_table: *const SysTable,
172 pub mem_manager_table: *const MemManagerTable,
173 pub traces_table: *const TracesTable,
174 pub mac_802_15_4_table: *const Mac802_15_4Table,
175}
diff --git a/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs b/embassy-stm32-wpan/src/unsafe_linked_list.rs
index 482e2bf5a..52c106fa2 100644
--- a/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs
+++ b/embassy-stm32-wpan/src/unsafe_linked_list.rs
@@ -57,6 +57,7 @@ impl LinkedListNode {
57 }); 57 });
58 } 58 }
59 59
60 /// Remove `node` from the linked list
60 pub unsafe fn remove_node(mut node: *mut LinkedListNode) { 61 pub unsafe fn remove_node(mut node: *mut LinkedListNode) {
61 interrupt::free(|_| { 62 interrupt::free(|_| {
62 (*(*node).prev).next = (*node).next; 63 (*(*node).prev).next = (*node).next;
@@ -64,6 +65,7 @@ impl LinkedListNode {
64 }); 65 });
65 } 66 }
66 67
68 /// Remove `list_head` into `node`
67 pub unsafe fn remove_head(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { 69 pub unsafe fn remove_head(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
68 interrupt::free(|_| { 70 interrupt::free(|_| {
69 *node = (*list_head).next; 71 *node = (*list_head).next;
@@ -71,10 +73,11 @@ impl LinkedListNode {
71 }); 73 });
72 } 74 }
73 75
74 pub unsafe fn remove_tail(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { 76 /// Remove `list_tail` into `node`
77 pub unsafe fn remove_tail(mut list_tail: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
75 interrupt::free(|_| { 78 interrupt::free(|_| {
76 *node = (*list_head).prev; 79 *node = (*list_tail).prev;
77 Self::remove_node((*list_head).prev); 80 Self::remove_node((*list_tail).prev);
78 }); 81 });
79 } 82 }
80 83
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/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/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs
index 0525d3f37..3132ab3e4 100644
--- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs
@@ -4,15 +4,15 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::tl_mbox::hci::RadioCoprocessor; 7use embassy_stm32::bind_interrupts;
8use embassy_stm32::tl_mbox::ipcc::Config; 8use embassy_stm32::ipcc::Config;
9use embassy_stm32::tl_mbox::TlMbox; 9use embassy_stm32_wpan::rc::RadioCoprocessor;
10use embassy_stm32::{bind_interrupts, tl_mbox}; 10use embassy_stm32_wpan::TlMbox;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13bind_interrupts!(struct Irqs{ 13bind_interrupts!(struct Irqs{
14 IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler; 14 IPCC_C1_RX => embassy_stm32_wpan::ReceiveInterruptHandler;
15 IPCC_C1_TX => tl_mbox::TransmitInterruptHandler; 15 IPCC_C1_TX => embassy_stm32_wpan::TransmitInterruptHandler;
16}); 16});
17 17
18#[embassy_executor::main] 18#[embassy_executor::main]
@@ -45,16 +45,16 @@ async fn main(_spawner: Spawner) {
45 info!("Hello World!"); 45 info!("Hello World!");
46 46
47 let config = Config::default(); 47 let config = Config::default();
48 let mbox = TlMbox::new(p.IPCC, Irqs, config); 48 let mbox = TlMbox::init(p.IPCC, Irqs, config);
49 49
50 let mut rc = RadioCoprocessor::new(mbox, Default::default()); 50 let mut rc = RadioCoprocessor::new(mbox);
51 rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]).unwrap();
52 51
53 let response = rc.read().await; 52 let response = rc.read().await;
54 info!("coprocessor ready {}", response); 53 info!("coprocessor ready {}", response);
55 54
55 rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]);
56 let response = rc.read().await; 56 let response = rc.read().await;
57 info!("coprocessor ready {}", response); 57 info!("ble reset rsp {}", response);
58 58
59 info!("Test OK"); 59 info!("Test OK");
60 cortex_m::asm::bkpt(); 60 cortex_m::asm::bkpt();