aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32-wpan/src/ble.rs4
-rw-r--r--embassy-stm32-wpan/src/evt.rs15
-rw-r--r--embassy-stm32-wpan/src/lib.rs12
-rw-r--r--embassy-stm32-wpan/src/mac.rs109
-rw-r--r--embassy-stm32-wpan/src/mm.rs3
-rw-r--r--embassy-stm32-wpan/src/tables.rs9
-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
9 files changed, 223 insertions, 7 deletions
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/evt.rs b/embassy-stm32-wpan/src/evt.rs
index a7b99e540..ee108ec88 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
@@ -129,6 +128,18 @@ impl EvtBox {
129 128
130impl Drop for EvtBox { 129impl Drop for EvtBox {
131 fn drop(&mut self) { 130 fn drop(&mut self) {
132 unsafe { mm::MemoryManager::drop_event_packet(self.ptr) }; 131 #[cfg(feature = "ble")]
132 unsafe {
133 use crate::mm;
134
135 mm::MemoryManager::drop_event_packet(self.ptr)
136 };
137
138 #[cfg(feature = "mac")]
139 unsafe {
140 use crate::mac;
141
142 mac::Mac::drop_event_packet(self.ptr)
143 }
133 } 144 }
134} 145}
diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs
index 1ddb3f2e0..5aec9933c 100644
--- a/embassy-stm32-wpan/src/lib.rs
+++ b/embassy-stm32-wpan/src/lib.rs
@@ -6,7 +6,6 @@ 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 embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; 9use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
11use embassy_stm32::interrupt; 10use embassy_stm32::interrupt;
12use embassy_stm32::ipcc::{Config, Ipcc, ReceiveInterruptHandler, TransmitInterruptHandler}; 11use embassy_stm32::ipcc::{Config, Ipcc, ReceiveInterruptHandler, TransmitInterruptHandler};
@@ -16,11 +15,14 @@ use sys::Sys;
16use tables::*; 15use tables::*;
17use unsafe_linked_list::LinkedListNode; 16use unsafe_linked_list::LinkedListNode;
18 17
18#[cfg(feature = "ble")]
19pub mod ble; 19pub mod ble;
20pub mod channels; 20pub mod channels;
21pub mod cmd; 21pub mod cmd;
22pub mod consts; 22pub mod consts;
23pub mod evt; 23pub mod evt;
24#[cfg(feature = "mac")]
25pub mod mac;
24pub mod mm; 26pub mod mm;
25pub mod shci; 27pub mod shci;
26pub mod sys; 28pub mod sys;
@@ -34,7 +36,10 @@ pub struct TlMbox<'d> {
34 36
35 pub sys_subsystem: Sys, 37 pub sys_subsystem: Sys,
36 pub mm_subsystem: MemoryManager, 38 pub mm_subsystem: MemoryManager,
37 pub ble_subsystem: Ble, 39 #[cfg(feature = "ble")]
40 pub ble_subsystem: ble::Ble,
41 #[cfg(feature = "mac")]
42 pub mac_subsystem: mac::Mac,
38} 43}
39 44
40impl<'d> TlMbox<'d> { 45impl<'d> TlMbox<'d> {
@@ -122,7 +127,10 @@ impl<'d> TlMbox<'d> {
122 Self { 127 Self {
123 _ipcc: ipcc, 128 _ipcc: ipcc,
124 sys_subsystem: sys::Sys::new(), 129 sys_subsystem: sys::Sys::new(),
130 #[cfg(feature = "ble")]
125 ble_subsystem: ble::Ble::new(), 131 ble_subsystem: ble::Ble::new(),
132 #[cfg(feature = "mac")]
133 mac_subsystem: mac::Mac::new(),
126 mm_subsystem: mm::MemoryManager::new(), 134 mm_subsystem: mm::MemoryManager::new(),
127 } 135 }
128 } 136 }
diff --git a/embassy-stm32-wpan/src/mac.rs b/embassy-stm32-wpan/src/mac.rs
new file mode 100644
index 000000000..9fbf37473
--- /dev/null
+++ b/embassy-stm32-wpan/src/mac.rs
@@ -0,0 +1,109 @@
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::cmd::CmdPacket;
12use crate::consts::TlPacketType;
13use crate::evt::{EvtBox, EvtPacket};
14use crate::tables::{
15 Mac802_15_4Table, MAC_802_15_4_CMD_BUFFER, MAC_802_15_4_NOTIF_RSP_EVT_BUFFER, TL_MAC_802_15_4_TABLE,
16};
17use crate::unsafe_linked_list::LinkedListNode;
18use crate::{channels, EVT_QUEUE};
19
20static MAC_WAKER: AtomicWaker = AtomicWaker::new();
21static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false);
22
23pub struct Mac {
24 phantom: PhantomData<Mac>,
25}
26
27impl Mac {
28 pub(crate) fn new() -> Self {
29 unsafe {
30 LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr());
31
32 TL_MAC_802_15_4_TABLE.as_mut_ptr().write_volatile(Mac802_15_4Table {
33 p_cmdrsp_buffer: MAC_802_15_4_CMD_BUFFER.as_mut_ptr().cast(),
34 p_notack_buffer: MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr().cast(),
35 evt_queue: ptr::null_mut(),
36 });
37 }
38
39 Self { phantom: PhantomData }
40 }
41
42 /// SAFETY: passing a pointer to something other than a managed event packet is UB
43 pub(crate) unsafe fn drop_event_packet(_: *mut EvtPacket) {
44 // Write the ack
45 CmdPacket::write_into(MAC_802_15_4_CMD_BUFFER.as_mut_ptr(), TlPacketType::OtAck, 0, &[]);
46
47 // Clear the rx flag
48 let _ = poll_once(Ipcc::receive::<bool>(
49 channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL,
50 || None,
51 ));
52
53 // Allow a new read call
54 MAC_EVT_OUT.store(false, Ordering::SeqCst);
55 MAC_WAKER.wake();
56 }
57
58 /// `HW_IPCC_MAC_802_15_4_EvtNot`
59 ///
60 /// This function will stall if the previous `EvtBox` has not been dropped
61 pub async fn read(&self) -> EvtBox {
62 // Wait for the last event box to be dropped
63 poll_fn(|cx| {
64 MAC_WAKER.register(cx.waker());
65 if MAC_EVT_OUT.load(Ordering::SeqCst) {
66 Poll::Pending
67 } else {
68 Poll::Ready(())
69 }
70 })
71 .await;
72
73 // Return a new event box
74 Ipcc::receive(channels::cpu2::IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL, || unsafe {
75 // The closure is not async, therefore the closure must execute to completion (cannot be dropped)
76 // Therefore, the event box is guaranteed to be cleaned up if it's not leaked
77 MAC_EVT_OUT.store(true, Ordering::SeqCst);
78
79 Some(EvtBox::new(MAC_802_15_4_NOTIF_RSP_EVT_BUFFER.as_mut_ptr() as *mut _))
80 })
81 .await
82 }
83
84 /// `HW_IPCC_MAC_802_15_4_CmdEvtNot`
85 pub async fn write_and_get_response(&self, opcode: u16, payload: &[u8]) -> u8 {
86 self.write(opcode, payload).await;
87 Ipcc::flush(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL).await;
88
89 unsafe {
90 let p_event_packet = MAC_802_15_4_CMD_BUFFER.as_ptr() as *const EvtPacket;
91 let p_mac_rsp_evt = &((*p_event_packet).evt_serial.evt.payload) as *const u8;
92
93 ptr::read_volatile(p_mac_rsp_evt)
94 }
95 }
96
97 /// `TL_MAC_802_15_4_SendCmd`
98 pub async fn write(&self, opcode: u16, payload: &[u8]) {
99 Ipcc::send(channels::cpu1::IPCC_MAC_802_15_4_CMD_RSP_CHANNEL, || unsafe {
100 CmdPacket::write_into(
101 MAC_802_15_4_CMD_BUFFER.as_mut_ptr(),
102 TlPacketType::OtCmd,
103 opcode,
104 payload,
105 );
106 })
107 .await;
108 }
109}
diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs
index dc499c1e7..047fddcd4 100644
--- a/embassy-stm32-wpan/src/mm.rs
+++ b/embassy-stm32-wpan/src/mm.rs
@@ -43,7 +43,8 @@ impl MemoryManager {
43 Self { phantom: PhantomData } 43 Self { phantom: PhantomData }
44 } 44 }
45 45
46 /// 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
47 pub(crate) unsafe fn drop_event_packet(evt: *mut EvtPacket) { 48 pub(crate) unsafe fn drop_event_packet(evt: *mut EvtPacket) {
48 interrupt::free(|_| unsafe { 49 interrupt::free(|_| unsafe {
49 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/tables.rs b/embassy-stm32-wpan/src/tables.rs
index 81873b147..2064910f0 100644
--- a/embassy-stm32-wpan/src/tables.rs
+++ b/embassy-stm32-wpan/src/tables.rs
@@ -230,6 +230,15 @@ pub static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
230pub static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); 230pub static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
231 231
232// --------------------- app tables --------------------- 232// --------------------- app tables ---------------------
233#[cfg(feature = "mac")]
234#[link_section = "MB_MEM2"]
235pub static mut MAC_802_15_4_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
236
237#[cfg(feature = "mac")]
238#[link_section = "MB_MEM2"]
239pub static mut MAC_802_15_4_NOTIF_RSP_EVT_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
240 MaybeUninit::uninit();
241
233#[link_section = "MB_MEM2"] 242#[link_section = "MB_MEM2"]
234pub static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit(); 243pub static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit();
235 244
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..f13f260b5
--- /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_ble_init(Default::default()).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}