diff options
| author | xoviat <[email protected]> | 2023-06-18 18:51:14 -0500 |
|---|---|---|
| committer | xoviat <[email protected]> | 2023-06-18 18:51:14 -0500 |
| commit | b95c0210b83d0742fa4663b2726e4e7b82a4e068 (patch) | |
| tree | f088a1d83cd416807079330515ae7514c3e10991 | |
| parent | 9f63158aad81486b4bd0ffe6f8d7103458ba360f (diff) | |
stm32/wpan: add draft mac mbox
| -rw-r--r-- | embassy-stm32-wpan/src/ble.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/evt.rs | 15 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/lib.rs | 12 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac.rs | 109 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mm.rs | 3 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/tables.rs | 9 | ||||
| -rw-r--r-- | examples/stm32wb/Cargo.toml | 14 | ||||
| -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.rs | 64 |
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 | ||
| 3 | use embassy_stm32::ipcc::Ipcc; | 3 | use embassy_stm32::ipcc::Ipcc; |
| 4 | 4 | ||
| 5 | use crate::channels; | ||
| 5 | use crate::cmd::CmdPacket; | 6 | use crate::cmd::CmdPacket; |
| 6 | use crate::consts::TlPacketType; | 7 | use crate::consts::TlPacketType; |
| 7 | use crate::evt::EvtBox; | 8 | use crate::evt::EvtBox; |
| 8 | use crate::tables::BleTable; | 9 | use crate::tables::{BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE}; |
| 9 | use crate::unsafe_linked_list::LinkedListNode; | 10 | use crate::unsafe_linked_list::LinkedListNode; |
| 10 | use crate::{channels, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE}; | ||
| 11 | 11 | ||
| 12 | pub struct Ble { | 12 | pub 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 @@ | |||
| 1 | use core::{ptr, slice}; | 1 | use core::{ptr, slice}; |
| 2 | 2 | ||
| 3 | use super::PacketHeader; | 3 | use super::PacketHeader; |
| 4 | use 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 | ||
| 130 | impl Drop for EvtBox { | 129 | impl 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; | |||
| 6 | use core::mem::MaybeUninit; | 6 | use core::mem::MaybeUninit; |
| 7 | use core::sync::atomic::{compiler_fence, Ordering}; | 7 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 8 | 8 | ||
| 9 | use ble::Ble; | ||
| 10 | use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; | 9 | use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; |
| 11 | use embassy_stm32::interrupt; | 10 | use embassy_stm32::interrupt; |
| 12 | use embassy_stm32::ipcc::{Config, Ipcc, ReceiveInterruptHandler, TransmitInterruptHandler}; | 11 | use embassy_stm32::ipcc::{Config, Ipcc, ReceiveInterruptHandler, TransmitInterruptHandler}; |
| @@ -16,11 +15,14 @@ use sys::Sys; | |||
| 16 | use tables::*; | 15 | use tables::*; |
| 17 | use unsafe_linked_list::LinkedListNode; | 16 | use unsafe_linked_list::LinkedListNode; |
| 18 | 17 | ||
| 18 | #[cfg(feature = "ble")] | ||
| 19 | pub mod ble; | 19 | pub mod ble; |
| 20 | pub mod channels; | 20 | pub mod channels; |
| 21 | pub mod cmd; | 21 | pub mod cmd; |
| 22 | pub mod consts; | 22 | pub mod consts; |
| 23 | pub mod evt; | 23 | pub mod evt; |
| 24 | #[cfg(feature = "mac")] | ||
| 25 | pub mod mac; | ||
| 24 | pub mod mm; | 26 | pub mod mm; |
| 25 | pub mod shci; | 27 | pub mod shci; |
| 26 | pub mod sys; | 28 | pub 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 | ||
| 40 | impl<'d> TlMbox<'d> { | 45 | impl<'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 @@ | |||
| 1 | use core::future::poll_fn; | ||
| 2 | use core::marker::PhantomData; | ||
| 3 | use core::ptr; | ||
| 4 | use core::sync::atomic::{AtomicBool, Ordering}; | ||
| 5 | use core::task::Poll; | ||
| 6 | |||
| 7 | use embassy_futures::poll_once; | ||
| 8 | use embassy_stm32::ipcc::Ipcc; | ||
| 9 | use embassy_sync::waitqueue::AtomicWaker; | ||
| 10 | |||
| 11 | use crate::cmd::CmdPacket; | ||
| 12 | use crate::consts::TlPacketType; | ||
| 13 | use crate::evt::{EvtBox, EvtPacket}; | ||
| 14 | use 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 | }; | ||
| 17 | use crate::unsafe_linked_list::LinkedListNode; | ||
| 18 | use crate::{channels, EVT_QUEUE}; | ||
| 19 | |||
| 20 | static MAC_WAKER: AtomicWaker = AtomicWaker::new(); | ||
| 21 | static MAC_EVT_OUT: AtomicBool = AtomicBool::new(false); | ||
| 22 | |||
| 23 | pub struct Mac { | ||
| 24 | phantom: PhantomData<Mac>, | ||
| 25 | } | ||
| 26 | |||
| 27 | impl 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(); | |||
| 230 | pub static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | 230 | pub 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"] | ||
| 235 | pub static mut MAC_802_15_4_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); | ||
| 236 | |||
| 237 | #[cfg(feature = "mac")] | ||
| 238 | #[link_section = "MB_MEM2"] | ||
| 239 | pub 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"] |
| 234 | pub static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit(); | 243 | pub 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" | |||
| 20 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 20 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
| 21 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 21 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
| 22 | heapless = { version = "0.7.5", default-features = false } | 22 | heapless = { version = "0.7.5", default-features = false } |
| 23 | |||
| 24 | |||
| 25 | [features] | ||
| 26 | default = ["ble"] | ||
| 27 | mac = ["embassy-stm32-wpan/mac"] | ||
| 28 | ble = ["embassy-stm32-wpan/ble"] | ||
| 29 | |||
| 30 | [[bin]] | ||
| 31 | name = "tl_mbox_ble" | ||
| 32 | required-features = ["ble"] | ||
| 33 | |||
| 34 | [[bin]] | ||
| 35 | name = "tl_mbox_mac" | ||
| 36 | required-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 | |||
| 5 | use defmt::*; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_stm32::bind_interrupts; | ||
| 8 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | ||
| 9 | use embassy_stm32_wpan::TlMbox; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | bind_interrupts!(struct Irqs{ | ||
| 13 | IPCC_C1_RX => ReceiveInterruptHandler; | ||
| 14 | IPCC_C1_TX => TransmitInterruptHandler; | ||
| 15 | }); | ||
| 16 | |||
| 17 | #[embassy_executor::main] | ||
| 18 | async 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 | } | ||
