aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32-wpan/src/ble.rs16
-rw-r--r--embassy-stm32-wpan/src/lib.rs31
-rw-r--r--embassy-stm32-wpan/src/mm.rs13
-rw-r--r--embassy-stm32-wpan/src/sys.rs45
-rw-r--r--examples/stm32wb/src/bin/tl_mbox.rs2
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_tx_rx.rs13
-rw-r--r--tests/stm32/src/bin/tl_mbox.rs51
7 files changed, 89 insertions, 82 deletions
diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs
index a39198d06..f0bd6f48c 100644
--- a/embassy-stm32-wpan/src/ble.rs
+++ b/embassy-stm32-wpan/src/ble.rs
@@ -1,3 +1,5 @@
1use core::marker::PhantomData;
2
1use embassy_stm32::ipcc::Ipcc; 3use embassy_stm32::ipcc::Ipcc;
2 4
3use crate::cmd::CmdPacket; 5use crate::cmd::CmdPacket;
@@ -7,10 +9,12 @@ use crate::tables::BleTable;
7use crate::unsafe_linked_list::LinkedListNode; 9use crate::unsafe_linked_list::LinkedListNode;
8use crate::{channels, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE}; 10use crate::{channels, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE};
9 11
10pub struct Ble; 12pub struct Ble {
13 phantom: PhantomData<Ble>,
14}
11 15
12impl Ble { 16impl Ble {
13 pub(super) fn enable() { 17 pub(crate) fn new() -> Self {
14 unsafe { 18 unsafe {
15 LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); 19 LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr());
16 20
@@ -21,9 +25,11 @@ impl Ble {
21 phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(), 25 phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(),
22 }); 26 });
23 } 27 }
28
29 Self { phantom: PhantomData }
24 } 30 }
25 /// `HW_IPCC_BLE_EvtNot` 31 /// `HW_IPCC_BLE_EvtNot`
26 pub async fn read() -> EvtBox { 32 pub async fn read(&self) -> EvtBox {
27 Ipcc::receive(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, || unsafe { 33 Ipcc::receive(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, || unsafe {
28 if let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) { 34 if let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) {
29 Some(EvtBox::new(node_ptr.cast())) 35 Some(EvtBox::new(node_ptr.cast()))
@@ -35,7 +41,7 @@ impl Ble {
35 } 41 }
36 42
37 /// `TL_BLE_SendCmd` 43 /// `TL_BLE_SendCmd`
38 pub async fn write(opcode: u16, payload: &[u8]) { 44 pub async fn write(&self, opcode: u16, payload: &[u8]) {
39 Ipcc::send(channels::cpu1::IPCC_BLE_CMD_CHANNEL, || unsafe { 45 Ipcc::send(channels::cpu1::IPCC_BLE_CMD_CHANNEL, || unsafe {
40 CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload); 46 CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload);
41 }) 47 })
@@ -43,7 +49,7 @@ impl Ble {
43 } 49 }
44 50
45 /// `TL_BLE_SendAclData` 51 /// `TL_BLE_SendAclData`
46 pub async fn acl_write(handle: u16, payload: &[u8]) { 52 pub async fn acl_write(&self, handle: u16, payload: &[u8]) {
47 Ipcc::send(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, || unsafe { 53 Ipcc::send(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, || unsafe {
48 CmdPacket::write_into( 54 CmdPacket::write_into(
49 HCI_ACL_DATA_BUFFER.as_mut_ptr() as *mut _, 55 HCI_ACL_DATA_BUFFER.as_mut_ptr() as *mut _,
diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs
index 2f694acf8..833db0df3 100644
--- a/embassy-stm32-wpan/src/lib.rs
+++ b/embassy-stm32-wpan/src/lib.rs
@@ -6,6 +6,7 @@ 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;
9use cmd::CmdPacket; 10use cmd::CmdPacket;
10use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 11use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
11use embassy_stm32::interrupt; 12use embassy_stm32::interrupt;
@@ -16,9 +17,10 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
16use embassy_sync::channel::Channel; 17use embassy_sync::channel::Channel;
17use embassy_sync::signal::Signal; 18use embassy_sync::signal::Signal;
18use evt::{CcEvt, EvtBox}; 19use evt::{CcEvt, EvtBox};
20use mm::MemoryManager;
21use sys::Sys;
19use tables::{ 22use tables::{
20 BleTable, DeviceInfoTable, Mac802_15_4Table, MemManagerTable, RefTable, SysTable, ThreadTable, TracesTable, 23 BleTable, DeviceInfoTable, Mac802_15_4Table, MemManagerTable, RefTable, SysTable, ThreadTable, TracesTable,
21 WirelessFwInfoTable,
22}; 24};
23use unsafe_linked_list::LinkedListNode; 25use unsafe_linked_list::LinkedListNode;
24 26
@@ -142,6 +144,10 @@ static STATE: Signal<CriticalSectionRawMutex, ()> = Signal::new();
142 144
143pub struct TlMbox<'d> { 145pub struct TlMbox<'d> {
144 _ipcc: PeripheralRef<'d, IPCC>, 146 _ipcc: PeripheralRef<'d, IPCC>,
147
148 pub sys_subsystem: Sys,
149 pub mm_subsystem: MemoryManager,
150 pub ble_subsystem: Ble,
145} 151}
146 152
147impl<'d> TlMbox<'d> { 153impl<'d> TlMbox<'d> {
@@ -226,9 +232,9 @@ impl<'d> TlMbox<'d> {
226 232
227 Ipcc::enable(config); 233 Ipcc::enable(config);
228 234
229 sys::Sys::enable(); 235 let sys = sys::Sys::new();
230 ble::Ble::enable(); 236 let ble = ble::Ble::new();
231 mm::MemoryManager::enable(); 237 let mm = mm::MemoryManager::new();
232 238
233 // enable interrupts 239 // enable interrupts
234 interrupt::typelevel::IPCC_C1_RX::unpend(); 240 interrupt::typelevel::IPCC_C1_RX::unpend();
@@ -239,18 +245,11 @@ impl<'d> TlMbox<'d> {
239 245
240 STATE.reset(); 246 STATE.reset();
241 247
242 Self { _ipcc: ipcc } 248 Self {
243 } 249 _ipcc: ipcc,
244 250 sys_subsystem: sys,
245 /// Returns CPU2 wireless firmware information (if present). 251 ble_subsystem: ble,
246 pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> { 252 mm_subsystem: mm,
247 let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table };
248
249 // Zero version indicates that CPU2 wasn't active and didn't fill the information table
250 if info.version != 0 {
251 Some(*info)
252 } else {
253 None
254 } 253 }
255 } 254 }
256} 255}
diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs
index d0551d690..21f42409a 100644
--- a/embassy-stm32-wpan/src/mm.rs
+++ b/embassy-stm32-wpan/src/mm.rs
@@ -1,6 +1,7 @@
1//! Memory manager routines 1//! Memory manager routines
2 2
3use core::future::poll_fn; 3use core::future::poll_fn;
4use core::marker::PhantomData;
4use core::task::Poll; 5use core::task::Poll;
5 6
6use cortex_m::interrupt; 7use cortex_m::interrupt;
@@ -17,10 +18,12 @@ use crate::{
17 18
18static MM_WAKER: AtomicWaker = AtomicWaker::new(); 19static MM_WAKER: AtomicWaker = AtomicWaker::new();
19 20
20pub struct MemoryManager; 21pub struct MemoryManager {
22 phantom: PhantomData<MemoryManager>,
23}
21 24
22impl MemoryManager { 25impl MemoryManager {
23 pub fn enable() { 26 pub(crate) fn new() -> Self {
24 unsafe { 27 unsafe {
25 LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); 28 LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr());
26 LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); 29 LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr());
@@ -35,10 +38,12 @@ impl MemoryManager {
35 tracespoolsize: 0, 38 tracespoolsize: 0,
36 }); 39 });
37 } 40 }
41
42 Self { phantom: PhantomData }
38 } 43 }
39 44
40 /// SAFETY: passing a pointer to something other than an event packet is UB 45 /// SAFETY: passing a pointer to something other than an event packet is UB
41 pub unsafe fn drop_event_packet(evt: *mut EvtPacket) { 46 pub(crate) unsafe fn drop_event_packet(evt: *mut EvtPacket) {
42 interrupt::free(|_| unsafe { 47 interrupt::free(|_| unsafe {
43 LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _); 48 LinkedListNode::insert_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), evt as *mut _);
44 }); 49 });
@@ -46,7 +51,7 @@ impl MemoryManager {
46 MM_WAKER.wake(); 51 MM_WAKER.wake();
47 } 52 }
48 53
49 pub async fn run_queue() { 54 pub async fn run_queue(&self) {
50 loop { 55 loop {
51 poll_fn(|cx| unsafe { 56 poll_fn(|cx| unsafe {
52 MM_WAKER.register(cx.waker()); 57 MM_WAKER.register(cx.waker());
diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs
index 78c357b3f..a185cd4f1 100644
--- a/embassy-stm32-wpan/src/sys.rs
+++ b/embassy-stm32-wpan/src/sys.rs
@@ -1,16 +1,20 @@
1use core::marker::PhantomData;
2
1use crate::cmd::CmdPacket; 3use crate::cmd::CmdPacket;
2use crate::consts::TlPacketType; 4use crate::consts::TlPacketType;
3use crate::evt::EvtBox; 5use crate::evt::EvtBox;
4use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT}; 6use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT};
5use crate::tables::SysTable; 7use crate::tables::{SysTable, WirelessFwInfoTable};
6use crate::unsafe_linked_list::LinkedListNode; 8use crate::unsafe_linked_list::LinkedListNode;
7use crate::{channels, Ipcc, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; 9use crate::{channels, Ipcc, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE};
8 10
9pub struct Sys; 11pub struct Sys {
12 phantom: PhantomData<Sys>,
13}
10 14
11impl Sys { 15impl Sys {
12 /// TL_Sys_Init 16 /// TL_Sys_Init
13 pub fn enable() { 17 pub(crate) fn new() -> Self {
14 unsafe { 18 unsafe {
15 LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); 19 LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr());
16 20
@@ -19,30 +23,33 @@ impl Sys {
19 sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), 23 sys_queue: SYSTEM_EVT_QUEUE.as_ptr(),
20 }); 24 });
21 } 25 }
26
27 Self { phantom: PhantomData }
28 }
29
30 /// Returns CPU2 wireless firmware information (if present).
31 pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> {
32 let info = unsafe { TL_DEVICE_INFO_TABLE.as_mut_ptr().read_volatile().wireless_fw_info_table };
33
34 // Zero version indicates that CPU2 wasn't active and didn't fill the information table
35 if info.version != 0 {
36 Some(info)
37 } else {
38 None
39 }
22 } 40 }
23 41
24 // pub async fn shci_c2_ble_init(&mut self, param: ShciBleInitCmdParam) -> SchiCommandStatus { 42 pub fn write(&self, opcode: u16, payload: &[u8]) {
25 // let command_event = self
26 // .write_and_get_response(TlPacketType::SysCmd, ShciOpcode::BleInit as u16, param.payload())
27 // .await;
28 //
29 // let payload = command_event.payload[0];
30 // // info!("payload: {:x}", payload);
31 //
32 // payload.try_into().unwrap()
33 // }
34
35 pub fn write(opcode: u16, payload: &[u8]) {
36 unsafe { 43 unsafe {
37 CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode, payload); 44 CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode, payload);
38 } 45 }
39 } 46 }
40 47
41 pub async fn shci_c2_ble_init(param: ShciBleInitCmdParam) { 48 pub async fn shci_c2_ble_init(&self, param: ShciBleInitCmdParam) {
42 debug!("sending SHCI"); 49 debug!("sending SHCI");
43 50
44 Ipcc::send(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, || { 51 Ipcc::send(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, || {
45 Self::write(SCHI_OPCODE_BLE_INIT, param.payload()); 52 self.write(SCHI_OPCODE_BLE_INIT, param.payload());
46 }) 53 })
47 .await; 54 .await;
48 55
@@ -50,7 +57,7 @@ impl Sys {
50 } 57 }
51 58
52 /// `HW_IPCC_SYS_EvtNot` 59 /// `HW_IPCC_SYS_EvtNot`
53 pub async fn read() -> EvtBox { 60 pub async fn read(&self) -> EvtBox {
54 Ipcc::receive(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, || unsafe { 61 Ipcc::receive(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, || unsafe {
55 if let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) { 62 if let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) {
56 Some(EvtBox::new(node_ptr.cast())) 63 Some(EvtBox::new(node_ptr.cast()))
diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs
index b010fdff1..9fc4b8aac 100644
--- a/examples/stm32wb/src/bin/tl_mbox.rs
+++ b/examples/stm32wb/src/bin/tl_mbox.rs
@@ -48,7 +48,7 @@ async fn main(_spawner: Spawner) {
48 let mbox = TlMbox::init(p.IPCC, Irqs, config); 48 let mbox = TlMbox::init(p.IPCC, Irqs, config);
49 49
50 loop { 50 loop {
51 let wireless_fw_info = mbox.wireless_fw_info(); 51 let wireless_fw_info = mbox.sys_subsystem.wireless_fw_info();
52 match wireless_fw_info { 52 match wireless_fw_info {
53 None => info!("not yet initialized"), 53 None => info!("not yet initialized"),
54 Some(fw_info) => { 54 Some(fw_info) => {
diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs
index 84a4f78e4..439bd01ac 100644
--- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs
@@ -6,8 +6,6 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::bind_interrupts; 7use embassy_stm32::bind_interrupts;
8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 8use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
9use embassy_stm32_wpan::ble::Ble;
10use embassy_stm32_wpan::sys::Sys;
11use embassy_stm32_wpan::TlMbox; 9use embassy_stm32_wpan::TlMbox;
12use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
13 11
@@ -46,15 +44,18 @@ async fn main(_spawner: Spawner) {
46 info!("Hello World!"); 44 info!("Hello World!");
47 45
48 let config = Config::default(); 46 let config = Config::default();
49 let _ = TlMbox::init(p.IPCC, Irqs, config); 47 let mbox = TlMbox::init(p.IPCC, Irqs, config);
50 48
51 Sys::shci_c2_ble_init(Default::default()).await; 49 let sys_event = mbox.sys_subsystem.read().await;
50 info!("sys event: {}", sys_event.payload());
51
52 mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await;
52 53
53 info!("starting ble..."); 54 info!("starting ble...");
54 Ble::write(0x0c, &[]).await; 55 mbox.ble_subsystem.write(0x0c, &[]).await;
55 56
56 info!("waiting for ble..."); 57 info!("waiting for ble...");
57 let ble_event = Ble::read().await; 58 let ble_event = mbox.ble_subsystem.read().await;
58 59
59 info!("ble event: {}", ble_event.payload()); 60 info!("ble event: {}", ble_event.payload());
60 61
diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs
index 259889e35..f6641ae31 100644
--- a/tests/stm32/src/bin/tl_mbox.rs
+++ b/tests/stm32/src/bin/tl_mbox.rs
@@ -13,8 +13,6 @@ use embassy_executor::Spawner;
13use embassy_futures::poll_once; 13use embassy_futures::poll_once;
14use embassy_stm32::bind_interrupts; 14use embassy_stm32::bind_interrupts;
15use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 15use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
16use embassy_stm32_wpan::ble::Ble;
17use embassy_stm32_wpan::sys::Sys;
18use embassy_stm32_wpan::{mm, TlMbox}; 16use embassy_stm32_wpan::{mm, TlMbox};
19use embassy_time::{Duration, Timer}; 17use embassy_time::{Duration, Timer};
20 18
@@ -24,8 +22,8 @@ bind_interrupts!(struct Irqs{
24}); 22});
25 23
26#[embassy_executor::task] 24#[embassy_executor::task]
27async fn run_mm_queue() { 25async fn run_mm_queue(memory_manager: mm::MemoryManager) {
28 mm::MemoryManager::run_queue().await; 26 memory_manager.run_queue().await;
29} 27}
30 28
31#[embassy_executor::main] 29#[embassy_executor::main]
@@ -33,50 +31,41 @@ async fn main(spawner: Spawner) {
33 let p = embassy_stm32::init(config()); 31 let p = embassy_stm32::init(config());
34 info!("Hello World!"); 32 info!("Hello World!");
35 33
36 spawner.spawn(run_mm_queue()).unwrap();
37
38 let config = Config::default(); 34 let config = Config::default();
39 let mbox = TlMbox::init(p.IPCC, Irqs, config); 35 let mbox = TlMbox::init(p.IPCC, Irqs, config);
40 36
41 let ready_event = Sys::read().await; 37 spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap();
42 let _ = poll_once(Sys::read()); // clear rx not 38
39 let ready_event = mbox.sys_subsystem.read().await;
40 let _ = poll_once(mbox.sys_subsystem.read()); // clear rx not
43 41
44 info!("coprocessor ready {}", ready_event.payload()); 42 info!("coprocessor ready {}", ready_event.payload());
45 43
46 // test memory manager 44 // test memory manager
47 mem::drop(ready_event); 45 mem::drop(ready_event);
48 46
49 loop { 47 let fw_info = mbox.sys_subsystem.wireless_fw_info().unwrap();
50 let wireless_fw_info = mbox.wireless_fw_info(); 48 let version_major = fw_info.version_major();
51 match wireless_fw_info { 49 let version_minor = fw_info.version_minor();
52 None => {} 50 let subversion = fw_info.subversion();
53 Some(fw_info) => {
54 let version_major = fw_info.version_major();
55 let version_minor = fw_info.version_minor();
56 let subversion = fw_info.subversion();
57
58 let sram2a_size = fw_info.sram2a_size();
59 let sram2b_size = fw_info.sram2b_size();
60 51
61 info!( 52 let sram2a_size = fw_info.sram2a_size();
62 "version {}.{}.{} - SRAM2a {} - SRAM2b {}", 53 let sram2b_size = fw_info.sram2b_size();
63 version_major, version_minor, subversion, sram2a_size, sram2b_size
64 );
65 54
66 break; 55 info!(
67 } 56 "version {}.{}.{} - SRAM2a {} - SRAM2b {}",
68 } 57 version_major, version_minor, subversion, sram2a_size, sram2b_size
58 );
69 59
70 Timer::after(Duration::from_millis(50)).await; 60 Timer::after(Duration::from_millis(50)).await;
71 }
72 61
73 Sys::shci_c2_ble_init(Default::default()).await; 62 mbox.sys_subsystem.shci_c2_ble_init(Default::default()).await;
74 63
75 info!("starting ble..."); 64 info!("starting ble...");
76 Ble::write(0x0c, &[]).await; 65 mbox.ble_subsystem.write(0x0c, &[]).await;
77 66
78 info!("waiting for ble..."); 67 info!("waiting for ble...");
79 let ble_event = Ble::read().await; 68 let ble_event = mbox.ble_subsystem.read().await;
80 69
81 info!("ble event: {}", ble_event.payload()); 70 info!("ble event: {}", ble_event.payload());
82 71