aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32-wpan/Cargo.toml3
-rw-r--r--embassy-stm32-wpan/src/ble.rs4
-rw-r--r--embassy-stm32-wpan/src/cmd.rs2
-rw-r--r--embassy-stm32-wpan/src/consts.rs34
-rw-r--r--embassy-stm32-wpan/src/evt.rs86
-rw-r--r--embassy-stm32-wpan/src/lib.rs146
-rw-r--r--embassy-stm32-wpan/src/mac.rs111
-rw-r--r--embassy-stm32-wpan/src/mm.rs16
-rw-r--r--embassy-stm32-wpan/src/shci.rs350
-rw-r--r--embassy-stm32-wpan/src/sys.rs40
-rw-r--r--embassy-stm32-wpan/src/tables.rs97
-rw-r--r--embassy-stm32/src/ipcc.rs12
-rw-r--r--examples/stm32wb/Cargo.toml14
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_ble.rs (renamed from examples/stm32wb/src/bin/tl_mbox_tx_rx.rs)0
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_mac.rs64
-rw-r--r--tests/stm32/Cargo.toml2
-rw-r--r--tests/stm32/src/bin/tl_mbox.rs8
17 files changed, 727 insertions, 262 deletions
diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml
index 1c1b57b36..f9023ed79 100644
--- a/embassy-stm32-wpan/Cargo.toml
+++ b/embassy-stm32-wpan/Cargo.toml
@@ -27,6 +27,9 @@ bit_field = "0.10.2"
27[features] 27[features]
28defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] 28defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"]
29 29
30ble = []
31mac = []
32
30stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] 33stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ]
31stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] 34stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ]
32stm32wb30ce = [ "embassy-stm32/stm32wb30ce" ] 35stm32wb30ce = [ "embassy-stm32/stm32wb30ce" ]
diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs
index f0bd6f48c..60e0cbdf8 100644
--- a/embassy-stm32-wpan/src/ble.rs
+++ b/embassy-stm32-wpan/src/ble.rs
@@ -2,12 +2,12 @@ use core::marker::PhantomData;
2 2
3use embassy_stm32::ipcc::Ipcc; 3use embassy_stm32::ipcc::Ipcc;
4 4
5use crate::channels;
5use crate::cmd::CmdPacket; 6use crate::cmd::CmdPacket;
6use crate::consts::TlPacketType; 7use crate::consts::TlPacketType;
7use crate::evt::EvtBox; 8use crate::evt::EvtBox;
8use crate::tables::BleTable; 9use crate::tables::{BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE};
9use crate::unsafe_linked_list::LinkedListNode; 10use crate::unsafe_linked_list::LinkedListNode;
10use crate::{channels, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE};
11 11
12pub struct Ble { 12pub struct Ble {
13 phantom: PhantomData<Ble>, 13 phantom: PhantomData<Ble>,
diff --git a/embassy-stm32-wpan/src/cmd.rs b/embassy-stm32-wpan/src/cmd.rs
index edca82390..c8056aaa7 100644
--- a/embassy-stm32-wpan/src/cmd.rs
+++ b/embassy-stm32-wpan/src/cmd.rs
@@ -37,7 +37,7 @@ pub struct CmdSerialStub {
37} 37}
38 38
39#[derive(Copy, Clone, Default)] 39#[derive(Copy, Clone, Default)]
40#[repr(C, packed)] 40#[repr(C, packed(4))]
41pub struct CmdPacket { 41pub struct CmdPacket {
42 pub header: PacketHeader, 42 pub header: PacketHeader,
43 pub cmdserial: CmdSerial, 43 pub cmdserial: CmdSerial,
diff --git a/embassy-stm32-wpan/src/consts.rs b/embassy-stm32-wpan/src/consts.rs
index caf26c06b..9a107306c 100644
--- a/embassy-stm32-wpan/src/consts.rs
+++ b/embassy-stm32-wpan/src/consts.rs
@@ -1,5 +1,8 @@
1use core::convert::TryFrom; 1use core::convert::TryFrom;
2 2
3use crate::evt::CsEvt;
4use crate::PacketHeader;
5
3#[derive(Debug)] 6#[derive(Debug)]
4#[repr(C)] 7#[repr(C)]
5pub enum TlPacketType { 8pub enum TlPacketType {
@@ -53,3 +56,34 @@ impl TryFrom<u8> for TlPacketType {
53 } 56 }
54 } 57 }
55} 58}
59
60pub const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::<PacketHeader>();
61pub const TL_EVT_HEADER_SIZE: usize = 3;
62pub const TL_CS_EVT_SIZE: usize = core::mem::size_of::<CsEvt>();
63
64/**
65 * Queue length of BLE Event
66 * This parameter defines the number of asynchronous events that can be stored in the HCI layer before
67 * being reported to the application. When a command is sent to the BLE core coprocessor, the HCI layer
68 * is waiting for the event with the Num_HCI_Command_Packets set to 1. The receive queue shall be large
69 * enough to store all asynchronous events received in between.
70 * When CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE is set to 27, this allow to store three 255 bytes long asynchronous events
71 * between the HCI command and its event.
72 * This parameter depends on the value given to CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE. When the queue size is to small,
73 * the system may hang if the queue is full with asynchronous events and the HCI layer is still waiting
74 * for a CC/CS event, In that case, the notification TL_BLE_HCI_ToNot() is called to indicate
75 * to the application a HCI command did not receive its command event within 30s (Default HCI Timeout).
76 */
77pub const CFG_TL_BLE_EVT_QUEUE_LENGTH: usize = 5;
78pub const CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255;
79pub const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE;
80
81pub const POOL_SIZE: usize = CFG_TL_BLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4);
82
83pub const fn divc(x: usize, y: usize) -> usize {
84 (x + y - 1) / y
85}
86
87pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE;
88#[allow(dead_code)]
89pub const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE;
diff --git a/embassy-stm32-wpan/src/evt.rs b/embassy-stm32-wpan/src/evt.rs
index 3a9d03576..47bdc49bf 100644
--- a/embassy-stm32-wpan/src/evt.rs
+++ b/embassy-stm32-wpan/src/evt.rs
@@ -1,7 +1,6 @@
1use core::{ptr, slice}; 1use core::{ptr, slice};
2 2
3use super::PacketHeader; 3use super::PacketHeader;
4use crate::mm;
5 4
6/** 5/**
7 * The payload of `Evt` for a command status event 6 * The payload of `Evt` for a command status event
@@ -46,15 +45,15 @@ pub struct AsynchEvt {
46 payload: [u8; 1], 45 payload: [u8; 1],
47} 46}
48 47
49#[derive(Copy, Clone, Default)] 48#[derive(Copy, Clone)]
50#[repr(C, packed)] 49#[repr(C, packed)]
51pub struct Evt { 50pub struct Evt {
52 pub evt_code: u8, 51 pub evt_code: u8,
53 pub payload_len: u8, 52 pub payload_len: u8,
54 pub payload: [u8; 1], 53 pub payload: [u8; 255],
55} 54}
56 55
57#[derive(Copy, Clone, Default)] 56#[derive(Copy, Clone)]
58#[repr(C, packed)] 57#[repr(C, packed)]
59pub struct EvtSerial { 58pub struct EvtSerial {
60 pub kind: u8, 59 pub kind: u8,
@@ -62,6 +61,7 @@ pub struct EvtSerial {
62} 61}
63 62
64#[derive(Copy, Clone, Default)] 63#[derive(Copy, Clone, Default)]
64#[repr(C, packed)]
65pub struct EvtStub { 65pub struct EvtStub {
66 pub kind: u8, 66 pub kind: u8,
67 pub evt_code: u8, 67 pub evt_code: u8,
@@ -75,7 +75,7 @@ pub struct EvtStub {
75/// Be careful that the asynchronous events reported by the CPU2 on the system channel do 75/// Be careful that the asynchronous events reported by the CPU2 on the system channel do
76/// include the header and shall use `EvtPacket` format. Only the command response format on the 76/// include the header and shall use `EvtPacket` format. Only the command response format on the
77/// system channel is different. 77/// system channel is different.
78#[derive(Copy, Clone, Default)] 78#[derive(Copy, Clone)]
79#[repr(C, packed)] 79#[repr(C, packed)]
80pub struct EvtPacket { 80pub struct EvtPacket {
81 pub header: PacketHeader, 81 pub header: PacketHeader,
@@ -114,7 +114,7 @@ impl EvtBox {
114 } 114 }
115 } 115 }
116 116
117 pub fn payload<'a>(&self) -> &'a [u8] { 117 pub fn payload<'a>(&'a self) -> &'a [u8] {
118 unsafe { 118 unsafe {
119 let p_payload_len = &(*self.ptr).evt_serial.evt.payload_len as *const u8; 119 let p_payload_len = &(*self.ptr).evt_serial.evt.payload_len as *const u8;
120 let p_payload = &(*self.ptr).evt_serial.evt.payload as *const u8; 120 let p_payload = &(*self.ptr).evt_serial.evt.payload as *const u8;
@@ -124,72 +124,22 @@ impl EvtBox {
124 slice::from_raw_parts(p_payload, payload_len as usize) 124 slice::from_raw_parts(p_payload, payload_len as usize)
125 } 125 }
126 } 126 }
127
128 // TODO: bring back acl
129
130 // /// writes an underlying [`EvtPacket`] into the provided buffer.
131 // /// Returns the number of bytes that were written.
132 // /// Returns an error if event kind is unknown or if provided buffer size is not enough.
133 // #[allow(clippy::result_unit_err)]
134 // pub fn write(&self, buf: &mut [u8]) -> Result<usize, ()> {
135 // unsafe {
136 // let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?;
137 //
138 // let evt_data: *const EvtPacket = self.ptr.cast();
139 // let evt_serial: *const EvtSerial = &(*evt_data).evt_serial;
140 // let evt_serial_buf: *const u8 = evt_serial.cast();
141 //
142 // let acl_data: *const AclDataPacket = self.ptr.cast();
143 // let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial;
144 // let acl_serial_buf: *const u8 = acl_serial.cast();
145 //
146 // if let TlPacketType::AclData = evt_kind {
147 // let len = (*acl_serial).length as usize + 5;
148 // if len > buf.len() {
149 // return Err(());
150 // }
151 //
152 // core::ptr::copy(evt_serial_buf, buf.as_mut_ptr(), len);
153 //
154 // Ok(len)
155 // } else {
156 // let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE;
157 // if len > buf.len() {
158 // return Err(());
159 // }
160 //
161 // core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len);
162 //
163 // Ok(len)
164 // }
165 // }
166 // }
167 //
168 // /// returns the size of a buffer required to hold this event
169 // #[allow(clippy::result_unit_err)]
170 // pub fn size(&self) -> Result<usize, ()> {
171 // unsafe {
172 // let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?;
173 //
174 // let evt_data: *const EvtPacket = self.ptr.cast();
175 // let evt_serial: *const EvtSerial = &(*evt_data).evt_serial;
176 //
177 // let acl_data: *const AclDataPacket = self.ptr.cast();
178 // let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial;
179 //
180 // if let TlPacketType::AclData = evt_kind {
181 // Ok((*acl_serial).length as usize + 5)
182 // } else {
183 // Ok((*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE)
184 // }
185 // }
186 // }
187} 127}
188 128
189impl Drop for EvtBox { 129impl Drop for EvtBox {
190 fn drop(&mut self) { 130 fn drop(&mut self) {
191 trace!("evt box drop packet"); 131 #[cfg(feature = "ble")]
132 unsafe {
133 use crate::mm;
134
135 mm::MemoryManager::drop_event_packet(self.ptr)
136 };
192 137
193 unsafe { mm::MemoryManager::drop_event_packet(self.ptr) }; 138 #[cfg(feature = "mac")]
139 unsafe {
140 use crate::mac;
141
142 mac::Mac::drop_event_packet(self.ptr)
143 }
194 } 144 }
195} 145}
diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs
index 833db0df3..5aec9933c 100644
--- a/embassy-stm32-wpan/src/lib.rs
+++ b/embassy-stm32-wpan/src/lib.rs
@@ -6,148 +6,40 @@ pub mod fmt;
6use core::mem::MaybeUninit; 6use core::mem::MaybeUninit;
7use core::sync::atomic::{compiler_fence, Ordering}; 7use core::sync::atomic::{compiler_fence, Ordering};
8 8
9use ble::Ble;
10use cmd::CmdPacket;
11use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 9use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
12use embassy_stm32::interrupt; 10use embassy_stm32::interrupt;
13use embassy_stm32::interrupt::typelevel::Interrupt;
14use embassy_stm32::ipcc::{Config, Ipcc, ReceiveInterruptHandler, TransmitInterruptHandler}; 11use embassy_stm32::ipcc::{Config, Ipcc, ReceiveInterruptHandler, TransmitInterruptHandler};
15use embassy_stm32::peripherals::IPCC; 12use embassy_stm32::peripherals::IPCC;
16use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
17use embassy_sync::channel::Channel;
18use embassy_sync::signal::Signal;
19use evt::{CcEvt, EvtBox};
20use mm::MemoryManager; 13use mm::MemoryManager;
21use sys::Sys; 14use sys::Sys;
22use tables::{ 15use tables::*;
23 BleTable, DeviceInfoTable, Mac802_15_4Table, MemManagerTable, RefTable, SysTable, ThreadTable, TracesTable,
24};
25use unsafe_linked_list::LinkedListNode; 16use unsafe_linked_list::LinkedListNode;
26 17
18#[cfg(feature = "ble")]
27pub mod ble; 19pub mod ble;
28pub mod channels; 20pub mod channels;
29pub mod cmd; 21pub mod cmd;
30pub mod consts; 22pub mod consts;
31pub mod evt; 23pub mod evt;
24#[cfg(feature = "mac")]
25pub mod mac;
32pub mod mm; 26pub mod mm;
33pub mod shci; 27pub mod shci;
34pub mod sys; 28pub mod sys;
35pub mod tables; 29pub mod tables;
36pub mod unsafe_linked_list; 30pub mod unsafe_linked_list;
37 31
38#[link_section = "TL_REF_TABLE"]
39pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit();
40
41#[link_section = "MB_MEM1"]
42static mut TL_DEVICE_INFO_TABLE: MaybeUninit<DeviceInfoTable> = MaybeUninit::uninit();
43
44#[link_section = "MB_MEM1"]
45static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit();
46
47#[link_section = "MB_MEM1"]
48static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit();
49
50#[link_section = "MB_MEM1"]
51static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit();
52
53#[link_section = "MB_MEM1"]
54static mut TL_MEM_MANAGER_TABLE: MaybeUninit<MemManagerTable> = MaybeUninit::uninit();
55
56#[link_section = "MB_MEM1"]
57static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit();
58
59#[link_section = "MB_MEM1"]
60static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit();
61
62#[link_section = "MB_MEM2"]
63static mut FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
64
65// Not in shared RAM
66static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
67
68#[allow(dead_code)] // Not used currently but reserved
69#[link_section = "MB_MEM2"]
70static mut TRACES_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
71
72type PacketHeader = LinkedListNode; 32type PacketHeader = LinkedListNode;
73 33
74const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::<PacketHeader>();
75const TL_EVT_HEADER_SIZE: usize = 3;
76const TL_CS_EVT_SIZE: usize = core::mem::size_of::<evt::CsEvt>();
77
78#[link_section = "MB_MEM2"]
79static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> =
80 MaybeUninit::uninit();
81
82#[link_section = "MB_MEM2"]
83static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
84
85#[link_section = "MB_MEM2"]
86static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
87
88#[link_section = "MB_MEM2"]
89pub static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
90
91/**
92 * Queue length of BLE Event
93 * This parameter defines the number of asynchronous events that can be stored in the HCI layer before
94 * being reported to the application. When a command is sent to the BLE core coprocessor, the HCI layer
95 * is waiting for the event with the Num_HCI_Command_Packets set to 1. The receive queue shall be large
96 * enough to store all asynchronous events received in between.
97 * When CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE is set to 27, this allow to store three 255 bytes long asynchronous events
98 * between the HCI command and its event.
99 * This parameter depends on the value given to CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE. When the queue size is to small,
100 * the system may hang if the queue is full with asynchronous events and the HCI layer is still waiting
101 * for a CC/CS event, In that case, the notification TL_BLE_HCI_ToNot() is called to indicate
102 * to the application a HCI command did not receive its command event within 30s (Default HCI Timeout).
103 */
104const CFG_TLBLE_EVT_QUEUE_LENGTH: usize = 5;
105const CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255;
106const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE;
107
108const fn divc(x: usize, y: usize) -> usize {
109 ((x) + (y) - 1) / (y)
110}
111
112const POOL_SIZE: usize = CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4);
113
114#[link_section = "MB_MEM2"]
115static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit();
116
117#[link_section = "MB_MEM2"]
118static mut SYS_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
119 MaybeUninit::uninit();
120
121#[link_section = "MB_MEM2"]
122static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
123 MaybeUninit::uninit();
124
125#[link_section = "MB_MEM2"]
126static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
127
128#[link_section = "MB_MEM2"]
129// fuck these "magic" numbers from ST ---v---v
130static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit();
131
132// TODO: remove these items
133
134#[allow(dead_code)]
135/// current event that is produced during IPCC IRQ handler execution
136/// on SYS channel
137static EVT_CHANNEL: Channel<CriticalSectionRawMutex, EvtBox, 32> = Channel::new();
138
139#[allow(dead_code)]
140/// last received Command Complete event
141static LAST_CC_EVT: Signal<CriticalSectionRawMutex, CcEvt> = Signal::new();
142
143static STATE: Signal<CriticalSectionRawMutex, ()> = Signal::new();
144
145pub struct TlMbox<'d> { 34pub struct TlMbox<'d> {
146 _ipcc: PeripheralRef<'d, IPCC>, 35 _ipcc: PeripheralRef<'d, IPCC>,
147 36
148 pub sys_subsystem: Sys, 37 pub sys_subsystem: Sys,
149 pub mm_subsystem: MemoryManager, 38 pub mm_subsystem: MemoryManager,
150 pub ble_subsystem: Ble, 39 #[cfg(feature = "ble")]
40 pub ble_subsystem: ble::Ble,
41 #[cfg(feature = "mac")]
42 pub mac_subsystem: mac::Mac,
151} 43}
152 44
153impl<'d> TlMbox<'d> { 45impl<'d> TlMbox<'d> {
@@ -232,24 +124,14 @@ impl<'d> TlMbox<'d> {
232 124
233 Ipcc::enable(config); 125 Ipcc::enable(config);
234 126
235 let sys = sys::Sys::new();
236 let ble = ble::Ble::new();
237 let mm = mm::MemoryManager::new();
238
239 // enable interrupts
240 interrupt::typelevel::IPCC_C1_RX::unpend();
241 interrupt::typelevel::IPCC_C1_TX::unpend();
242
243 unsafe { interrupt::typelevel::IPCC_C1_RX::enable() };
244 unsafe { interrupt::typelevel::IPCC_C1_TX::enable() };
245
246 STATE.reset();
247
248 Self { 127 Self {
249 _ipcc: ipcc, 128 _ipcc: ipcc,
250 sys_subsystem: sys, 129 sys_subsystem: sys::Sys::new(),
251 ble_subsystem: ble, 130 #[cfg(feature = "ble")]
252 mm_subsystem: mm, 131 ble_subsystem: ble::Ble::new(),
132 #[cfg(feature = "mac")]
133 mac_subsystem: mac::Mac::new(),
134 mm_subsystem: mm::MemoryManager::new(),
253 } 135 }
254 } 136 }
255} 137}
diff --git a/embassy-stm32-wpan/src/mac.rs b/embassy-stm32-wpan/src/mac.rs
new file mode 100644
index 000000000..d2be1b85c
--- /dev/null
+++ b/embassy-stm32-wpan/src/mac.rs
@@ -0,0 +1,111 @@
1use core::future::poll_fn;
2use core::marker::PhantomData;
3use core::ptr;
4use core::sync::atomic::{AtomicBool, Ordering};
5use core::task::Poll;
6
7use embassy_futures::poll_once;
8use embassy_stm32::ipcc::Ipcc;
9use embassy_sync::waitqueue::AtomicWaker;
10
11use crate::channels;
12use crate::cmd::CmdPacket;
13use crate::consts::TlPacketType;
14use crate::evt::{EvtBox, EvtPacket};
15use crate::tables::{
16 Mac802_15_4Table, MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, TL_MAC_802_15_4_TABLE,
17};
18
19static MAC_WAKER: AtomicWaker = AtomicWaker::new();
20static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false);
21
22pub struct Mac {
23 phantom: PhantomData<Mac>,
24}
25
26impl Mac {
27 pub(crate) fn new() -> Self {
28 unsafe {
29 TL_MAC_802_15_4_TABLE.as_mut_ptr().write_volatile(Mac802_15_4Table {
30 p_cmdrsp_buffer: MAC_802_15_4_CMD_BUFFER.as_mut_ptr().cast(),
31 p_notack_buffer: MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr().cast(),
32 evt_queue: ptr::null_mut(),
33 });
34 }
35
36 Self { phantom: PhantomData }
37 }
38
39 /// SAFETY: passing a pointer to something other than a managed event packet is UB
40 pub(crate) unsafe fn drop_event_packet(_: *mut EvtPacket) {
41 // Write the ack
42 CmdPacket::write_into(
43 MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _,
44 TlPacketType::OtAck,
45 0,
46 &[],
47 );
48
49 // Clear the rx flag
50 let _ = poll_once(Ipcc::receive::<bool>(
51 channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL,
52 || None,
53 ));
54
55 // Allow a new read call
56 MAC_EVT_OUT.store(false, Ordering::SeqCst);
57 MAC_WAKER.wake();
58 }
59
60 /// `HW_IPCC_MAC_802_15_4_EvtNot`
61 ///
62 /// This function will stall if the previous `EvtBox` has not been dropped
63 pub async fn read(&self) -> EvtBox {
64 // Wait for the last event box to be dropped
65 poll_fn(|cx| {
66 MAC_WAKER.register(cx.waker());
67 if MAC_EVT_OUT.load(Ordering::SeqCst) {
68 Poll::Pending
69 } else {
70 Poll::Ready(())
71 }
72 })
73 .await;
74
75 // Return a new event box
76 Ipcc::receive(channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, || unsafe {
77 // The closure is not async, therefore the closure must execute to completion (cannot be dropped)
78 // Therefore, the event box is guaranteed to be cleaned up if it's not leaked
79 MAC_EVT_OUT.store(true, Ordering::SeqCst);
80
81 Some(EvtBox::new(MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _))
82 })
83 .await
84 }
85
86 /// `HW_IPCC_MAC_802_15_4_CmdEvtNot`
87 pub async fn write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 {
88 self.write(opcode, payload).await;
89 Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await;
90
91 unsafe {
92 let p_event_packet = MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket;
93 let p_mac_rsp_evt = &((*p_event_packet).evt_serial.evt.payload) as *const u8;
94
95 ptr::read_volatile(p_mac_rsp_evt)
96 }
97 }
98
99 /// `TL_MAC_802_15_4_SendCmd`
100 pub async fn write(&self, opcode: u16, payload: &[u8]) {
101 Ipcc::send(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL, || unsafe {
102 CmdPacket::write_into(
103 MAC_802_15_4_CMD_BUFFER.as_mut_ptr(),
104 TlPacketType::OtCmd,
105 opcode,
106 payload,
107 );
108 })
109 .await;
110 }
111}
diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs
index 21f42409a..047fddcd4 100644
--- a/embassy-stm32-wpan/src/mm.rs
+++ b/embassy-stm32-wpan/src/mm.rs
@@ -1,22 +1,23 @@
1//! Memory manager routines 1//! Memory manager routines
2
3use core::future::poll_fn; 2use core::future::poll_fn;
4use core::marker::PhantomData; 3use core::marker::PhantomData;
4use core::mem::MaybeUninit;
5use core::task::Poll; 5use core::task::Poll;
6 6
7use cortex_m::interrupt; 7use cortex_m::interrupt;
8use embassy_stm32::ipcc::Ipcc; 8use embassy_stm32::ipcc::Ipcc;
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
10 10
11use crate::channels;
12use crate::consts::POOL_SIZE;
11use crate::evt::EvtPacket; 13use crate::evt::EvtPacket;
12use crate::tables::MemManagerTable; 14use crate::tables::{
13use crate::unsafe_linked_list::LinkedListNode; 15 MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE,
14use crate::{
15 channels, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF,
16 TL_MEM_MANAGER_TABLE,
17}; 16};
17use crate::unsafe_linked_list::LinkedListNode;
18 18
19static MM_WAKER: AtomicWaker = AtomicWaker::new(); 19static MM_WAKER: AtomicWaker = AtomicWaker::new();
20static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
20 21
21pub struct MemoryManager { 22pub struct MemoryManager {
22 phantom: PhantomData<MemoryManager>, 23 phantom: PhantomData<MemoryManager>,
@@ -42,7 +43,8 @@ impl MemoryManager {
42 Self { phantom: PhantomData } 43 Self { phantom: PhantomData }
43 } 44 }
44 45
45 /// SAFETY: passing a pointer to something other than an event packet is UB 46 #[allow(dead_code)]
47 /// SAFETY: passing a pointer to something other than a managed event packet is UB
46 pub(crate) unsafe fn drop_event_packet(evt: *mut EvtPacket) { 48 pub(crate) unsafe fn drop_event_packet(evt: *mut EvtPacket) {
47 interrupt::free(|_| unsafe { 49 interrupt::free(|_| unsafe {
48 LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _); 50 LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _);
diff --git a/embassy-stm32-wpan/src/shci.rs b/embassy-stm32-wpan/src/shci.rs
index cdf027d5e..30d689716 100644
--- a/embassy-stm32-wpan/src/shci.rs
+++ b/embassy-stm32-wpan/src/shci.rs
@@ -1,39 +1,346 @@
1use core::{mem, slice}; 1use core::{mem, slice};
2 2
3use super::{TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE}; 3use crate::consts::{TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE};
4 4
5pub const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66; 5const SHCI_OGF: u16 = 0x3F;
6 6
7#[derive(Debug, Clone, Copy)] 7const fn opcode(ogf: u16, ocf: u16) -> isize {
8 ((ogf << 10) + ocf) as isize
9}
10
11#[allow(dead_code)]
12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13pub enum SchiCommandStatus {
14 ShciSuccess = 0x00,
15 ShciUnknownCmd = 0x01,
16 ShciMemoryCapacityExceededErrCode = 0x07,
17 ShciErrUnsupportedFeature = 0x11,
18 ShciErrInvalidHciCmdParams = 0x12,
19 ShciErrInvalidParams = 0x42, /* only used for release < v1.13.0 */
20 ShciErrInvalidParamsV2 = 0x92, /* available for release >= v1.13.0 */
21 ShciFusCmdNotSupported = 0xFF,
22}
23
24impl TryFrom<u8> for SchiCommandStatus {
25 type Error = ();
26
27 fn try_from(v: u8) -> Result<Self, Self::Error> {
28 match v {
29 x if x == SchiCommandStatus::ShciSuccess as u8 => Ok(SchiCommandStatus::ShciSuccess),
30 x if x == SchiCommandStatus::ShciUnknownCmd as u8 => Ok(SchiCommandStatus::ShciUnknownCmd),
31 x if x == SchiCommandStatus::ShciMemoryCapacityExceededErrCode as u8 => {
32 Ok(SchiCommandStatus::ShciMemoryCapacityExceededErrCode)
33 }
34 x if x == SchiCommandStatus::ShciErrUnsupportedFeature as u8 => {
35 Ok(SchiCommandStatus::ShciErrUnsupportedFeature)
36 }
37 x if x == SchiCommandStatus::ShciErrInvalidHciCmdParams as u8 => {
38 Ok(SchiCommandStatus::ShciErrInvalidHciCmdParams)
39 }
40 x if x == SchiCommandStatus::ShciErrInvalidParams as u8 => Ok(SchiCommandStatus::ShciErrInvalidParams), /* only used for release < v1.13.0 */
41 x if x == SchiCommandStatus::ShciErrInvalidParamsV2 as u8 => Ok(SchiCommandStatus::ShciErrInvalidParamsV2), /* available for release >= v1.13.0 */
42 x if x == SchiCommandStatus::ShciFusCmdNotSupported as u8 => Ok(SchiCommandStatus::ShciFusCmdNotSupported),
43 _ => Err(()),
44 }
45 }
46}
47
48#[allow(dead_code)]
49#[cfg_attr(feature = "defmt", derive(defmt::Format))]
50pub enum ShciOpcode {
51 // 0x50 reserved
52 // 0x51 reserved
53 FusGetState = opcode(SHCI_OGF, 0x52),
54 // 0x53 reserved
55 FusFirmwareUpgrade = opcode(SHCI_OGF, 0x54),
56 FusFirmwareDelete = opcode(SHCI_OGF, 0x55),
57 FusUpdateAuthKey = opcode(SHCI_OGF, 0x56),
58 FusLockAuthKey = opcode(SHCI_OGF, 0x57),
59 FusStoreUserKey = opcode(SHCI_OGF, 0x58),
60 FusLoadUserKey = opcode(SHCI_OGF, 0x59),
61 FusStartWirelessStack = opcode(SHCI_OGF, 0x5a),
62 // 0x5b reserved
63 // 0x5c reserved
64 FusLockUserKey = opcode(SHCI_OGF, 0x5d),
65 FusUnloadUserKey = opcode(SHCI_OGF, 0x5e),
66 FusActivateAntirollback = opcode(SHCI_OGF, 0x5f),
67 // 0x60 reserved
68 // 0x61 reserved
69 // 0x62 reserved
70 // 0x63 reserved
71 // 0x64 reserved
72 // 0x65 reserved
73 BleInit = opcode(SHCI_OGF, 0x66),
74 ThreadInit = opcode(SHCI_OGF, 0x67),
75 DebugInit = opcode(SHCI_OGF, 0x68),
76 FlashEraseActivity = opcode(SHCI_OGF, 0x69),
77 ConcurrentSetMode = opcode(SHCI_OGF, 0x6a),
78 FlashStoreData = opcode(SHCI_OGF, 0x6b),
79 FlashEraseData = opcode(SHCI_OGF, 0x6c),
80 RadioAllowLowPower = opcode(SHCI_OGF, 0x6d),
81 Mac802_15_4Init = opcode(SHCI_OGF, 0x6e),
82 ReInit = opcode(SHCI_OGF, 0x6f),
83 ZigbeeInit = opcode(SHCI_OGF, 0x70),
84 LldTestsInit = opcode(SHCI_OGF, 0x71),
85 ExtraConfig = opcode(SHCI_OGF, 0x72),
86 SetFlashActivityControl = opcode(SHCI_OGF, 0x73),
87 BleLldInit = opcode(SHCI_OGF, 0x74),
88 Config = opcode(SHCI_OGF, 0x75),
89 ConcurrentGetNextBleEvtTime = opcode(SHCI_OGF, 0x76),
90 ConcurrentEnableNext802_15_4EvtNotification = opcode(SHCI_OGF, 0x77),
91 Mac802_15_4DeInit = opcode(SHCI_OGF, 0x78),
92}
93
94pub const SHCI_C2_CONFIG_EVTMASK1_BIT0_ERROR_NOTIF_ENABLE: u8 = 1 << 0;
95pub const SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE: u8 = 1 << 1;
96pub const SHCI_C2_CONFIG_EVTMASK1_BIT2_THREAD_NVM_RAM_UPDATE_ENABLE: u8 = 1 << 2;
97pub const SHCI_C2_CONFIG_EVTMASK1_BIT3_NVM_START_WRITE_ENABLE: u8 = 1 << 3;
98pub const SHCI_C2_CONFIG_EVTMASK1_BIT4_NVM_END_WRITE_ENABLE: u8 = 1 << 4;
99pub const SHCI_C2_CONFIG_EVTMASK1_BIT5_NVM_START_ERASE_ENABLE: u8 = 1 << 5;
100pub const SHCI_C2_CONFIG_EVTMASK1_BIT6_NVM_END_ERASE_ENABLE: u8 = 1 << 6;
101
102#[derive(Clone, Copy)]
103#[repr(C, packed)]
104pub struct ShciConfigParam {
105 pub payload_cmd_size: u8,
106 pub config: u8,
107 pub event_mask: u8,
108 pub spare: u8,
109 pub ble_nvm_ram_address: u32,
110 pub thread_nvm_ram_address: u32,
111 pub revision_id: u16,
112 pub device_id: u16,
113}
114
115impl ShciConfigParam {
116 pub fn payload<'a>(&'a self) -> &'a [u8] {
117 unsafe { slice::from_raw_parts(self as *const _ as *const u8, mem::size_of::<Self>()) }
118 }
119}
120
121impl Default for ShciConfigParam {
122 fn default() -> Self {
123 Self {
124 payload_cmd_size: (mem::size_of::<Self>() - 1) as u8,
125 config: 0,
126 event_mask: SHCI_C2_CONFIG_EVTMASK1_BIT0_ERROR_NOTIF_ENABLE
127 + SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE
128 + SHCI_C2_CONFIG_EVTMASK1_BIT2_THREAD_NVM_RAM_UPDATE_ENABLE
129 + SHCI_C2_CONFIG_EVTMASK1_BIT3_NVM_START_WRITE_ENABLE
130 + SHCI_C2_CONFIG_EVTMASK1_BIT4_NVM_END_WRITE_ENABLE
131 + SHCI_C2_CONFIG_EVTMASK1_BIT5_NVM_START_ERASE_ENABLE
132 + SHCI_C2_CONFIG_EVTMASK1_BIT6_NVM_END_ERASE_ENABLE,
133 spare: 0,
134 ble_nvm_ram_address: 0,
135 thread_nvm_ram_address: 0,
136 revision_id: 0,
137 device_id: 0,
138 }
139 }
140}
141
142#[derive(Clone, Copy)]
8#[repr(C, packed)] 143#[repr(C, packed)]
9pub struct ShciBleInitCmdParam { 144pub struct ShciBleInitCmdParam {
10 /// NOT USED CURRENTLY 145 /// NOT USED - shall be set to 0
11 pub p_ble_buffer_address: u32, 146 pub p_ble_buffer_address: u32,
12 147 /// NOT USED - shall be set to 0
13 /// Size of the Buffer allocated in pBleBufferAddress
14 pub ble_buffer_size: u32, 148 pub ble_buffer_size: u32,
15 149 /// Maximum number of attribute records related to all the required characteristics (excluding the services)
150 /// that can be stored in the GATT database, for the specific BLE user application.
151 /// For each characteristic, the number of attribute records goes from two to five depending on the characteristic properties:
152 /// - minimum of two (one for declaration and one for the value)
153 /// - add one more record for each additional property: notify or indicate, broadcast, extended property.
154 /// The total calculated value must be increased by 9, due to the records related to the standard attribute profile and
155 /// GAP service characteristics, and automatically added when initializing GATT and GAP layers
156 /// - Min value: <number of user attributes> + 9
157 /// - Max value: depending on the GATT database defined by user application
16 pub num_attr_record: u16, 158 pub num_attr_record: u16,
159 /// Defines the maximum number of services that can be stored in the GATT database. Note that the GAP and GATT services
160 /// are automatically added at initialization so this parameter must be the number of user services increased by two.
161 /// - Min value: <number of user service> + 2
162 /// - Max value: depending GATT database defined by user application
17 pub num_attr_serv: u16, 163 pub num_attr_serv: u16,
164 /// NOTE: This parameter is ignored by the CPU2 when the parameter "Options" is set to "LL_only" ( see Options description in that structure )
165 ///
166 /// Size of the storage area for the attribute values.
167 /// Each characteristic contributes to the attrValueArrSize value as follows:
168 /// - Characteristic value length plus:
169 /// + 5 bytes if characteristic UUID is 16 bits
170 /// + 19 bytes if characteristic UUID is 128 bits
171 /// + 2 bytes if characteristic has a server configuration descriptor
172 /// + 2 bytes * NumOfLinks if the characteristic has a client configuration descriptor
173 /// + 2 bytes if the characteristic has extended properties
174 /// Each descriptor contributes to the attrValueArrSize value as follows:
175 /// - Descriptor length
18 pub attr_value_arr_size: u16, 176 pub attr_value_arr_size: u16,
177 /// Maximum number of BLE links supported
178 /// - Min value: 1
179 /// - Max value: 8
19 pub num_of_links: u8, 180 pub num_of_links: u8,
181 /// Disable/enable the extended packet length BLE 5.0 feature
182 /// - Disable: 0
183 /// - Enable: 1
20 pub extended_packet_length_enable: u8, 184 pub extended_packet_length_enable: u8,
21 pub pr_write_list_size: u8, 185 /// NOTE: This parameter is ignored by the CPU2 when the parameter "Options" is set to "LL_only" ( see Options description in that structure )
22 pub mb_lock_count: u8, 186 ///
23 187 /// Maximum number of supported "prepare write request"
188 /// - Min value: given by the macro DEFAULT_PREP_WRITE_LIST_SIZE
189 /// - Max value: a value higher than the minimum required can be specified, but it is not recommended
190 pub prepare_write_list_size: u8,
191 /// NOTE: This parameter is overwritten by the CPU2 with an hardcoded optimal value when the parameter "Options" is set to "LL_only"
192 /// ( see Options description in that structure )
193 ///
194 /// Number of allocated memory blocks for the BLE stack
195 /// - Min value: given by the macro MBLOCKS_CALC
196 /// - Max value: a higher value can improve data throughput performance, but uses more memory
197 pub block_count: u8,
198 /// NOTE: This parameter is ignored by the CPU2 when the parameter "Options" is set to "LL_only" ( see Options description in that structure )
199 ///
200 /// Maximum ATT MTU size supported
201 /// - Min value: 23
202 /// - Max value: 512
24 pub att_mtu: u16, 203 pub att_mtu: u16,
204 /// The sleep clock accuracy (ppm value) that used in BLE connected slave mode to calculate the window widening
205 /// (in combination with the sleep clock accuracy sent by master in CONNECT_REQ PDU),
206 /// refer to BLE 5.0 specifications - Vol 6 - Part B - chap 4.5.7 and 4.2.2
207 /// - Min value: 0
208 /// - Max value: 500 (worst possible admitted by specification)
25 pub slave_sca: u16, 209 pub slave_sca: u16,
210 /// The sleep clock accuracy handled in master mode. It is used to determine the connection and advertising events timing.
211 /// It is transmitted to the slave in CONNEC_REQ PDU used by the slave to calculate the window widening,
212 /// see SlaveSca and Bluetooth Core Specification v5.0 Vol 6 - Part B - chap 4.5.7 and 4.2.2
213 /// Possible values:
214 /// - 251 ppm to 500 ppm: 0
215 /// - 151 ppm to 250 ppm: 1
216 /// - 101 ppm to 150 ppm: 2
217 /// - 76 ppm to 100 ppm: 3
218 /// - 51 ppm to 75 ppm: 4
219 /// - 31 ppm to 50 ppm: 5
220 /// - 21 ppm to 30 ppm: 6
221 /// - 0 ppm to 20 ppm: 7
26 pub master_sca: u8, 222 pub master_sca: u8,
223 /// Some information for Low speed clock mapped in bits field
224 /// - bit 0:
225 /// - 1: Calibration for the RF system wakeup clock source
226 /// - 0: No calibration for the RF system wakeup clock source
227 /// - bit 1:
228 /// - 1: STM32W5M Module device
229 /// - 0: Other devices as STM32WBxx SOC, STM32WB1M module
230 /// - bit 2:
231 /// - 1: HSE/1024 Clock config
232 /// - 0: LSE Clock config
27 pub ls_source: u8, 233 pub ls_source: u8,
234 /// This parameter determines the maximum duration of a slave connection event. When this duration is reached the slave closes
235 /// the current connections event (whatever is the CE_length parameter specified by the master in HCI_CREATE_CONNECTION HCI command),
236 /// expressed in units of 625/256 µs (~2.44 µs)
237 /// - Min value: 0 (if 0 is specified, the master and slave perform only a single TX-RX exchange per connection event)
238 /// - Max value: 1638400 (4000 ms). A higher value can be specified (max 0xFFFFFFFF) but results in a maximum connection time
239 /// of 4000 ms as specified. In this case the parameter is not applied, and the predicted CE length calculated on slave is not shortened
28 pub max_conn_event_length: u32, 240 pub max_conn_event_length: u32,
241 /// Startup time of the high speed (16 or 32 MHz) crystal oscillator in units of 625/256 µs (~2.44 µs).
242 /// - Min value: 0
243 /// - Max value: 820 (~2 ms). A higher value can be specified, but the value that implemented in stack is forced to ~2 ms
29 pub hs_startup_time: u16, 244 pub hs_startup_time: u16,
245 /// Viterbi implementation in BLE LL reception.
246 /// - 0: Enable
247 /// - 1: Disable
30 pub viterbi_enable: u8, 248 pub viterbi_enable: u8,
31 pub ll_only: u8, 249 /// - bit 0:
250 /// - 1: LL only
251 /// - 0: LL + host
252 /// - bit 1:
253 /// - 1: no service change desc.
254 /// - 0: with service change desc.
255 /// - bit 2:
256 /// - 1: device name Read-Only
257 /// - 0: device name R/W
258 /// - bit 3:
259 /// - 1: extended advertizing supported
260 /// - 0: extended advertizing not supported
261 /// - bit 4:
262 /// - 1: CS Algo #2 supported
263 /// - 0: CS Algo #2 not supported
264 /// - bit 5:
265 /// - 1: Reduced GATT database in NVM
266 /// - 0: Full GATT database in NVM
267 /// - bit 6:
268 /// - 1: GATT caching is used
269 /// - 0: GATT caching is not used
270 /// - bit 7:
271 /// - 1: LE Power Class 1
272 /// - 0: LE Power Classe 2-3
273 /// - other bits: complete with Options_extension flag
274 pub options: u8,
275 /// Reserved for future use - shall be set to 0
32 pub hw_version: u8, 276 pub hw_version: u8,
277 // /**
278 // * Maximum number of connection-oriented channels in initiator mode.
279 // * Range: 0 .. 64
280 // */
281 // pub max_coc_initiator_nbr: u8,
282 //
283 // /**
284 // * Minimum transmit power in dBm supported by the Controller.
285 // * Range: -127 .. 20
286 // */
287 // pub min_tx_power: i8,
288 //
289 // /**
290 // * Maximum transmit power in dBm supported by the Controller.
291 // * Range: -127 .. 20
292 // */
293 // pub max_tx_power: i8,
294 //
295 // /**
296 // * RX model configuration
297 // * - bit 0: 1: agc_rssi model improved vs RF blockers 0: Legacy agc_rssi model
298 // * - other bits: reserved ( shall be set to 0)
299 // */
300 // pub rx_model_config: u8,
301 //
302 // /* Maximum number of advertising sets.
303 // * Range: 1 .. 8 with limitation:
304 // * This parameter is linked to max_adv_data_len such as both compliant with allocated Total memory computed with BLE_EXT_ADV_BUFFER_SIZE based
305 // * on Max Extended advertising configuration supported.
306 // * This parameter is considered by the CPU2 when Options has SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV flag set
307 // */
308 // pub max_adv_set_nbr: u8,
309 //
310 // /* Maximum advertising data length (in bytes)
311 // * Range: 31 .. 1650 with limitation:
312 // * This parameter is linked to max_adv_set_nbr such as both compliant with allocated Total memory computed with BLE_EXT_ADV_BUFFER_SIZE based
313 // * on Max Extended advertising configuration supported.
314 // * This parameter is considered by the CPU2 when Options has SHCI_C2_BLE_INIT_OPTIONS_EXT_ADV flag set
315 // */
316 // pub max_adv_data_len: u16,
317 //
318 // /* RF TX Path Compensation Value (16-bit signed integer). Units: 0.1 dB.
319 // * Range: -1280 .. 1280
320 // */
321 // pub tx_path_compens: i16,
322 //
323 // /* RF RX Path Compensation Value (16-bit signed integer). Units: 0.1 dB.
324 // * Range: -1280 .. 1280
325 // */
326 // pub rx_path_compens: i16,
327 //
328 // /* BLE core specification version (8-bit unsigned integer).
329 // * values as: 11(5.2), 12(5.3)
330 // */
331 // pub ble_core_version: u8,
332 //
333 // /**
334 // * Options flags extension
335 // * - bit 0: 1: appearance Writable 0: appearance Read-Only
336 // * - bit 1: 1: Enhanced ATT supported 0: Enhanced ATT not supported
337 // * - other bits: reserved ( shall be set to 0)
338 // */
339 // pub options_extension: u8,
33} 340}
34 341
35impl ShciBleInitCmdParam { 342impl ShciBleInitCmdParam {
36 pub fn payload<'a>(&self) -> &'a [u8] { 343 pub fn payload<'a>(&'a self) -> &'a [u8] {
37 unsafe { slice::from_raw_parts(self as *const _ as *const u8, mem::size_of::<Self>()) } 344 unsafe { slice::from_raw_parts(self as *const _ as *const u8, mem::size_of::<Self>()) }
38 } 345 }
39} 346}
@@ -48,8 +355,8 @@ impl Default for ShciBleInitCmdParam {
48 attr_value_arr_size: 1344, 355 attr_value_arr_size: 1344,
49 num_of_links: 2, 356 num_of_links: 2,
50 extended_packet_length_enable: 1, 357 extended_packet_length_enable: 1,
51 pr_write_list_size: 0x3A, 358 prepare_write_list_size: 0x3A,
52 mb_lock_count: 0x79, 359 block_count: 0x79,
53 att_mtu: 156, 360 att_mtu: 156,
54 slave_sca: 500, 361 slave_sca: 500,
55 master_sca: 0, 362 master_sca: 0,
@@ -57,25 +364,12 @@ impl Default for ShciBleInitCmdParam {
57 max_conn_event_length: 0xFFFFFFFF, 364 max_conn_event_length: 0xFFFFFFFF,
58 hs_startup_time: 0x148, 365 hs_startup_time: 0x148,
59 viterbi_enable: 1, 366 viterbi_enable: 1,
60 ll_only: 0, 367 options: 0,
61 hw_version: 0, 368 hw_version: 0,
62 } 369 }
63 } 370 }
64} 371}
65 372
66#[derive(Debug, Clone, Copy, Default)]
67#[repr(C, packed)]
68pub struct ShciHeader {
69 metadata: [u32; 3],
70}
71
72#[derive(Debug, Clone, Copy)]
73#[repr(C, packed)]
74pub struct ShciBleInitCmdPacket {
75 pub header: ShciHeader,
76 pub param: ShciBleInitCmdParam,
77}
78
79pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE; 373pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE;
80#[allow(dead_code)] // Not used currently but reserved 374#[allow(dead_code)] // Not used currently but reserved
81const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; 375const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE;
diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs
index a185cd4f1..2b699b725 100644
--- a/embassy-stm32-wpan/src/sys.rs
+++ b/embassy-stm32-wpan/src/sys.rs
@@ -1,9 +1,11 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2use core::ptr;
2 3
3use crate::cmd::CmdPacket; 4use crate::cmd::CmdPacket;
4use crate::consts::TlPacketType; 5use crate::consts::TlPacketType;
5use crate::evt::EvtBox; 6use crate::evt::{CcEvt, EvtBox, EvtPacket};
6use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT}; 7#[allow(unused_imports)]
8use crate::shci::{SchiCommandStatus, ShciBleInitCmdParam, ShciOpcode};
7use crate::tables::{SysTable, WirelessFwInfoTable}; 9use crate::tables::{SysTable, WirelessFwInfoTable};
8use crate::unsafe_linked_list::LinkedListNode; 10use crate::unsafe_linked_list::LinkedListNode;
9use crate::{channels, Ipcc, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE}; 11use crate::{channels, Ipcc, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE};
@@ -39,21 +41,35 @@ impl Sys {
39 } 41 }
40 } 42 }
41 43
42 pub fn write(&self, opcode: u16, payload: &[u8]) { 44 pub async fn write(&self, opcode: ShciOpcode, payload: &[u8]) {
45 Ipcc::send(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, || unsafe {
46 CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode as u16, payload);
47 })
48 .await;
49 }
50
51 /// `HW_IPCC_SYS_CmdEvtNot`
52 pub async fn write_and_get_response(&self, opcode: ShciOpcode, payload: &[u8]) -> SchiCommandStatus {
53 self.write(opcode, payload).await;
54 Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await;
55
43 unsafe { 56 unsafe {
44 CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode, payload); 57 let p_event_packet = SYS_CMD_BUF.as_ptr() as *const EvtPacket;
58 let p_command_event = &((*p_event_packet).evt_serial.evt.payload) as *const _ as *const CcEvt;
59 let p_payload = &((*p_command_event).payload) as *const u8;
60
61 ptr::read_volatile(p_payload).try_into().unwrap()
45 } 62 }
46 } 63 }
47 64
48 pub async fn shci_c2_ble_init(&self, param: ShciBleInitCmdParam) { 65 #[cfg(feature = "mac")]
49 debug!("sending SHCI"); 66 pub async fn shci_c2_mac_802_15_4_init(&self) -> SchiCommandStatus {
50 67 self.write_and_get_response(ShciOpcode::Mac802_15_4Init, &[]).await
51 Ipcc::send(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, || { 68 }
52 self.write(SCHI_OPCODE_BLE_INIT, param.payload());
53 })
54 .await;
55 69
56 Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await; 70 #[cfg(feature = "ble")]
71 pub async fn shci_c2_ble_init(&self, param: ShciBleInitCmdParam) -> SchiCommandStatus {
72 self.write_and_get_response(ShciOpcode::BleInit, param.payload()).await
57 } 73 }
58 74
59 /// `HW_IPCC_SYS_EvtNot` 75 /// `HW_IPCC_SYS_EvtNot`
diff --git a/embassy-stm32-wpan/src/tables.rs b/embassy-stm32-wpan/src/tables.rs
index 151216958..3f26282c6 100644
--- a/embassy-stm32-wpan/src/tables.rs
+++ b/embassy-stm32-wpan/src/tables.rs
@@ -1,6 +1,9 @@
1use core::mem::MaybeUninit;
2
1use bit_field::BitField; 3use bit_field::BitField;
2 4
3use crate::cmd::{AclDataPacket, CmdPacket}; 5use crate::cmd::{AclDataPacket, CmdPacket};
6use crate::consts::{POOL_SIZE, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE};
4use crate::unsafe_linked_list::LinkedListNode; 7use crate::unsafe_linked_list::LinkedListNode;
5 8
6#[derive(Debug, Copy, Clone)] 9#[derive(Debug, Copy, Clone)]
@@ -161,6 +164,9 @@ pub struct Mac802_15_4Table {
161 pub evt_queue: *const u8, 164 pub evt_queue: *const u8,
162} 165}
163 166
167#[repr(C, align(4))]
168pub struct AlignedData<const L: usize>([u8; L]);
169
164/// Reference table. Contains pointers to all other tables. 170/// Reference table. Contains pointers to all other tables.
165#[derive(Debug, Copy, Clone)] 171#[derive(Debug, Copy, Clone)]
166#[repr(C)] 172#[repr(C)]
@@ -173,3 +179,94 @@ pub struct RefTable {
173 pub traces_table: *const TracesTable, 179 pub traces_table: *const TracesTable,
174 pub mac_802_15_4_table: *const Mac802_15_4Table, 180 pub mac_802_15_4_table: *const Mac802_15_4Table,
175} 181}
182
183// --------------------- ref table ---------------------
184#[link_section = "TL_REF_TABLE"]
185pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit();
186
187#[link_section = "MB_MEM1"]
188pub static mut TL_DEVICE_INFO_TABLE: MaybeUninit<DeviceInfoTable> = MaybeUninit::uninit();
189
190#[link_section = "MB_MEM1"]
191pub static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit();
192
193#[link_section = "MB_MEM1"]
194pub static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit();
195
196// #[link_section = "MB_MEM1"]
197// pub static mut TL_LLD_TESTS_TABLE: MaybeUninit<LldTestTable> = MaybeUninit::uninit();
198
199// #[link_section = "MB_MEM1"]
200// pub static mut TL_BLE_LLD_TABLE: MaybeUninit<BleLldTable> = MaybeUninit::uninit();
201
202#[link_section = "MB_MEM1"]
203pub static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit();
204
205#[link_section = "MB_MEM1"]
206pub static mut TL_MEM_MANAGER_TABLE: MaybeUninit<MemManagerTable> = MaybeUninit::uninit();
207
208#[link_section = "MB_MEM1"]
209pub static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit();
210
211#[link_section = "MB_MEM1"]
212pub static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit();
213
214// #[link_section = "MB_MEM1"]
215// pub static mut TL_ZIGBEE_TABLE: MaybeUninit<ZigbeeTable> = MaybeUninit::uninit();
216
217// --------------------- tables ---------------------
218#[link_section = "MB_MEM1"]
219pub static mut FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
220
221#[allow(dead_code)]
222#[link_section = "MB_MEM1"]
223pub static mut TRACES_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
224
225const CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE;
226
227#[link_section = "MB_MEM2"]
228pub static mut CS_BUFFER: MaybeUninit<AlignedData<CS_BUFFER_SIZE>> = MaybeUninit::uninit();
229
230#[link_section = "MB_MEM2"]
231pub static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
232
233#[link_section = "MB_MEM2"]
234pub static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
235
236// --------------------- app tables ---------------------
237#[cfg(feature = "mac")]
238#[link_section = "MB_MEM2"]
239pub static mut MAC_802_15_4_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
240
241#[cfg(feature = "mac")]
242const MAC_802_15_4_NOTIF_RSP_EVT_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255;
243
244#[cfg(feature = "mac")]
245#[link_section = "MB_MEM2"]
246pub static mut MAC_802_15_4_NOTIF_RSP_EVT_BUFFER: MaybeUninit<AlignedData<MAC_802_15_4_NOTIF_RSP_EVT_BUFFER_SIZE>> =
247 MaybeUninit::uninit();
248
249#[link_section = "MB_MEM2"]
250pub static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit();
251
252#[link_section = "MB_MEM2"]
253pub static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
254
255const SYS_SPARE_EVT_BUF_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255;
256
257#[link_section = "MB_MEM2"]
258pub static mut SYS_SPARE_EVT_BUF: MaybeUninit<AlignedData<SYS_SPARE_EVT_BUF_SIZE>> = MaybeUninit::uninit();
259
260#[link_section = "MB_MEM1"]
261pub static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
262
263const BLE_SPARE_EVT_BUF_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255;
264
265#[link_section = "MB_MEM2"]
266pub static mut BLE_SPARE_EVT_BUF: MaybeUninit<AlignedData<BLE_SPARE_EVT_BUF_SIZE>> = MaybeUninit::uninit();
267
268const HCI_ACL_DATA_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + 5 + 251;
269
270#[link_section = "MB_MEM2"]
271// fuck these "magic" numbers from ST ---v---v
272pub static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; HCI_ACL_DATA_BUFFER_SIZE]> = MaybeUninit::uninit();
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs
index 3062226c7..37f840c73 100644
--- a/embassy-stm32/src/ipcc.rs
+++ b/embassy-stm32/src/ipcc.rs
@@ -120,7 +120,6 @@ impl Ipcc {
120 let regs = IPCC::regs(); 120 let regs = IPCC::regs();
121 121
122 Self::flush(channel).await; 122 Self::flush(channel).await;
123 compiler_fence(Ordering::SeqCst);
124 123
125 f(); 124 f();
126 125
@@ -136,7 +135,7 @@ impl Ipcc {
136 135
137 // This is a race, but is nice for debugging 136 // This is a race, but is nice for debugging
138 if regs.cpu(0).sr().read().chf(channel as usize) { 137 if regs.cpu(0).sr().read().chf(channel as usize) {
139 trace!("ipcc: ch {}: wait for tx free", channel as u8); 138 trace!("ipcc: ch {}: wait for tx free", channel as u8);
140 } 139 }
141 140
142 poll_fn(|cx| { 141 poll_fn(|cx| {
@@ -165,7 +164,7 @@ impl Ipcc {
165 loop { 164 loop {
166 // This is a race, but is nice for debugging 165 // This is a race, but is nice for debugging
167 if !regs.cpu(1).sr().read().chf(channel as usize) { 166 if !regs.cpu(1).sr().read().chf(channel as usize) {
168 trace!("ipcc: ch {}: wait for rx occupied", channel as u8); 167 trace!("ipcc: ch {}: wait for rx occupied", channel as u8);
169 } 168 }
170 169
171 poll_fn(|cx| { 170 poll_fn(|cx| {
@@ -186,8 +185,7 @@ impl Ipcc {
186 }) 185 })
187 .await; 186 .await;
188 187
189 trace!("ipcc: ch {}: read data", channel as u8); 188 trace!("ipcc: ch {}: read data", channel as u8);
190 compiler_fence(Ordering::SeqCst);
191 189
192 match f() { 190 match f() {
193 Some(ret) => return ret, 191 Some(ret) => return ret,
@@ -237,7 +235,7 @@ pub(crate) mod sealed {
237 } 235 }
238 } 236 }
239 237
240 pub fn rx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { 238 pub const fn rx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker {
241 match channel { 239 match channel {
242 IpccChannel::Channel1 => &self.rx_wakers[0], 240 IpccChannel::Channel1 => &self.rx_wakers[0],
243 IpccChannel::Channel2 => &self.rx_wakers[1], 241 IpccChannel::Channel2 => &self.rx_wakers[1],
@@ -248,7 +246,7 @@ pub(crate) mod sealed {
248 } 246 }
249 } 247 }
250 248
251 pub fn tx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { 249 pub const fn tx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker {
252 match channel { 250 match channel {
253 IpccChannel::Channel1 => &self.tx_wakers[0], 251 IpccChannel::Channel1 => &self.tx_wakers[0],
254 IpccChannel::Channel2 => &self.tx_wakers[1], 252 IpccChannel::Channel2 => &self.tx_wakers[1],
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml
index 83a443754..e41424aad 100644
--- a/examples/stm32wb/Cargo.toml
+++ b/examples/stm32wb/Cargo.toml
@@ -20,3 +20,17 @@ embedded-hal = "0.2.6"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 20panic-probe = { version = "0.3", features = ["print-defmt"] }
21futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 21futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
22heapless = { version = "0.7.5", default-features = false } 22heapless = { version = "0.7.5", default-features = false }
23
24
25[features]
26default = ["ble"]
27mac = ["embassy-stm32-wpan/mac"]
28ble = ["embassy-stm32-wpan/ble"]
29
30[[bin]]
31name = "tl_mbox_ble"
32required-features = ["ble"]
33
34[[bin]]
35name = "tl_mbox_mac"
36required-features = ["mac"] \ No newline at end of file
diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_ble.rs
index 439bd01ac..439bd01ac 100644
--- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_ble.rs
diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs
new file mode 100644
index 000000000..a42939bbd
--- /dev/null
+++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs
@@ -0,0 +1,64 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::bind_interrupts;
8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
9use embassy_stm32_wpan::TlMbox;
10use {defmt_rtt as _, panic_probe as _};
11
12bind_interrupts!(struct Irqs{
13 IPCC_C1_RX => ReceiveInterruptHandler;
14 IPCC_C1_TX => TransmitInterruptHandler;
15});
16
17#[embassy_executor::main]
18async fn main(_spawner: Spawner) {
19 /*
20 How to make this work:
21
22 - Obtain a NUCLEO-STM32WB55 from your preferred supplier.
23 - Download and Install STM32CubeProgrammer.
24 - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from
25 gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x
26 - Open STM32CubeProgrammer
27 - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware.
28 - Once complete, click connect to connect to the device.
29 - On the left hand pane, click the RSS signal icon to open "Firmware Upgrade Services".
30 - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file
31 - Select that file, the memory address, "verify download", and then "Firmware Upgrade".
32 - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the
33 stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address.
34 - Select that file, the memory address, "verify download", and then "Firmware Upgrade".
35 - Select "Start Wireless Stack".
36 - Disconnect from the device.
37 - In the examples folder for stm32wb, modify the memory.x file to match your target device.
38 - Run this example.
39
40 Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name.
41 */
42
43 let p = embassy_stm32::init(Default::default());
44 info!("Hello World!");
45
46 let config = Config::default();
47 let mbox = TlMbox::init(p.IPCC, Irqs, config);
48
49 let sys_event = mbox.sys_subsystem.read().await;
50 info!("sys event: {}", sys_event.payload());
51
52 mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await;
53 //
54 // info!("starting ble...");
55 // mbox.ble_subsystem.write(0x0c, &[]).await;
56 //
57 // info!("waiting for ble...");
58 // let ble_event = mbox.ble_subsystem.read().await;
59 //
60 // info!("ble event: {}", ble_event.payload());
61
62 info!("Test OK");
63 cortex_m::asm::bkpt();
64}
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index 365f631b7..fe646927a 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -30,7 +30,7 @@ embassy-executor = { version = "0.2.0", path = "../../embassy-executor", feature
30embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] } 30embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] }
31embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] } 31embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] }
32embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 32embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
33embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg"] } 33embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg", "ble"] }
34 34
35defmt = "0.3.0" 35defmt = "0.3.0"
36defmt-rtt = "0.4" 36defmt-rtt = "0.4"
diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs
index f6641ae31..f47a89b6f 100644
--- a/tests/stm32/src/bin/tl_mbox.rs
+++ b/tests/stm32/src/bin/tl_mbox.rs
@@ -39,7 +39,7 @@ async fn main(spawner: Spawner) {
39 let ready_event = mbox.sys_subsystem.read().await; 39 let ready_event = mbox.sys_subsystem.read().await;
40 let _ = poll_once(mbox.sys_subsystem.read()); // clear rx not 40 let _ = poll_once(mbox.sys_subsystem.read()); // clear rx not
41 41
42 info!("coprocessor ready {}", ready_event.payload()); 42 info!("sys event {:x} : {:x}", ready_event.stub().kind, ready_event.payload());
43 43
44 // test memory manager 44 // test memory manager
45 mem::drop(ready_event); 45 mem::drop(ready_event);
@@ -59,7 +59,8 @@ async fn main(spawner: Spawner) {
59 59
60 Timer::after(Duration::from_millis(50)).await; 60 Timer::after(Duration::from_millis(50)).await;
61 61
62 mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await; 62 let result = mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await;
63 info!("subsystem initialization: {}", result);
63 64
64 info!("starting ble..."); 65 info!("starting ble...");
65 mbox.ble_subsystem.write(0x0c, &[]).await; 66 mbox.ble_subsystem.write(0x0c, &[]).await;
@@ -67,9 +68,8 @@ async fn main(spawner: Spawner) {
67 info!("waiting for ble..."); 68 info!("waiting for ble...");
68 let ble_event = mbox.ble_subsystem.read().await; 69 let ble_event = mbox.ble_subsystem.read().await;
69 70
70 info!("ble event: {}", ble_event.payload()); 71 info!("ble event {:x} : {:x}", ble_event.stub().kind, ble_event.payload());
71 72
72 Timer::after(Duration::from_millis(150)).await;
73 info!("Test OK"); 73 info!("Test OK");
74 cortex_m::asm::bkpt(); 74 cortex_m::asm::bkpt();
75} 75}