aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32-wpan/src/sub/ble.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-stm32-wpan/src/sub/ble.rs')
-rw-r--r--embassy-stm32-wpan/src/sub/ble.rs85
1 files changed, 51 insertions, 34 deletions
diff --git a/embassy-stm32-wpan/src/sub/ble.rs b/embassy-stm32-wpan/src/sub/ble.rs
index cd69a0479..d5ed2ca28 100644
--- a/embassy-stm32-wpan/src/sub/ble.rs
+++ b/embassy-stm32-wpan/src/sub/ble.rs
@@ -1,6 +1,6 @@
1use core::ptr; 1use core::ptr;
2 2
3use embassy_stm32::ipcc::Ipcc; 3use embassy_stm32::ipcc::{IpccRxChannel, IpccTxChannel};
4use hci::Opcode; 4use hci::Opcode;
5 5
6use crate::cmd::CmdPacket; 6use crate::cmd::CmdPacket;
@@ -9,7 +9,7 @@ use crate::evt::{EvtBox, EvtPacket, EvtStub};
9use crate::sub::mm; 9use crate::sub::mm;
10use crate::tables::{BLE_CMD_BUFFER, BleTable, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE}; 10use crate::tables::{BLE_CMD_BUFFER, BleTable, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE};
11use crate::unsafe_linked_list::LinkedListNode; 11use crate::unsafe_linked_list::LinkedListNode;
12use crate::{channels, evt}; 12use crate::evt;
13 13
14/// A guard that, once constructed, may be used to send BLE commands to CPU2. 14/// A guard that, once constructed, may be used to send BLE commands to CPU2.
15/// 15///
@@ -36,15 +36,21 @@ use crate::{channels, evt};
36/// # mbox.ble_subsystem.reset().await; 36/// # mbox.ble_subsystem.reset().await;
37/// # let _reset_response = mbox.ble_subsystem.read().await; 37/// # let _reset_response = mbox.ble_subsystem.read().await;
38/// ``` 38/// ```
39pub struct Ble { 39pub struct Ble<'a> {
40 _private: (), 40 hw_ipcc_ble_cmd_channel: IpccTxChannel<'a>,
41 ipcc_ble_event_channel: IpccRxChannel<'a>,
42 ipcc_hci_acl_data_channel: IpccTxChannel<'a>,
41} 43}
42 44
43impl Ble { 45impl<'a> Ble<'a> {
44 /// Constructs a guard that allows for BLE commands to be sent to CPU2. 46 /// Constructs a guard that allows for BLE commands to be sent to CPU2.
45 /// 47 ///
46 /// This takes the place of `TL_BLE_Init`, completing that step as laid out in AN5289, Fig 66. 48 /// This takes the place of `TL_BLE_Init`, completing that step as laid out in AN5289, Fig 66.
47 pub(crate) fn new() -> Self { 49 pub(crate) fn new(
50 hw_ipcc_ble_cmd_channel: IpccTxChannel<'a>,
51 ipcc_ble_event_channel: IpccRxChannel<'a>,
52 ipcc_hci_acl_data_channel: IpccTxChannel<'a>,
53 ) -> Self {
48 unsafe { 54 unsafe {
49 LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); 55 LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr());
50 56
@@ -56,44 +62,51 @@ impl Ble {
56 }); 62 });
57 } 63 }
58 64
59 Self { _private: () } 65 Self {
66 hw_ipcc_ble_cmd_channel,
67 ipcc_ble_event_channel,
68 ipcc_hci_acl_data_channel,
69 }
60 } 70 }
61 71
62 /// `HW_IPCC_BLE_EvtNot` 72 /// `HW_IPCC_BLE_EvtNot`
63 pub async fn tl_read(&self) -> EvtBox<Self> { 73 pub async fn tl_read(&mut self) -> EvtBox<Self> {
64 Ipcc::receive(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, || unsafe { 74 self.ipcc_ble_event_channel
65 if let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) { 75 .receive(|| unsafe {
66 Some(EvtBox::new(node_ptr.cast())) 76 if let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) {
67 } else { 77 Some(EvtBox::new(node_ptr.cast()))
68 None 78 } else {
69 } 79 None
70 }) 80 }
71 .await 81 })
82 .await
72 } 83 }
73 84
74 /// `TL_BLE_SendCmd` 85 /// `TL_BLE_SendCmd`
75 pub async fn tl_write(&self, opcode: u16, payload: &[u8]) { 86 pub async fn tl_write(&mut self, opcode: u16, payload: &[u8]) {
76 Ipcc::send(channels::cpu1::IPCC_BLE_CMD_CHANNEL, || unsafe { 87 self.hw_ipcc_ble_cmd_channel
77 CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload); 88 .send(|| unsafe {
78 }) 89 CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload);
79 .await; 90 })
91 .await;
80 } 92 }
81 93
82 /// `TL_BLE_SendAclData` 94 /// `TL_BLE_SendAclData`
83 pub async fn acl_write(&self, handle: u16, payload: &[u8]) { 95 pub async fn acl_write(&mut self, handle: u16, payload: &[u8]) {
84 Ipcc::send(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, || unsafe { 96 self.ipcc_hci_acl_data_channel
85 CmdPacket::write_into( 97 .send(|| unsafe {
86 HCI_ACL_DATA_BUFFER.as_mut_ptr() as *mut _, 98 CmdPacket::write_into(
87 TlPacketType::AclData, 99 HCI_ACL_DATA_BUFFER.as_mut_ptr() as *mut _,
88 handle, 100 TlPacketType::AclData,
89 payload, 101 handle,
90 ); 102 payload,
91 }) 103 );
92 .await; 104 })
105 .await;
93 } 106 }
94} 107}
95 108
96impl evt::MemoryManager for Ble { 109impl<'a> evt::MemoryManager for Ble<'a> {
97 /// SAFETY: passing a pointer to something other than a managed event packet is UB 110 /// SAFETY: passing a pointer to something other than a managed event packet is UB
98 unsafe fn drop_event_packet(evt: *mut EvtPacket) { 111 unsafe fn drop_event_packet(evt: *mut EvtPacket) {
99 let stub = unsafe { 112 let stub = unsafe {
@@ -110,13 +123,17 @@ impl evt::MemoryManager for Ble {
110 123
111pub extern crate stm32wb_hci as hci; 124pub extern crate stm32wb_hci as hci;
112 125
113impl hci::Controller for Ble { 126impl<'a> hci::Controller for Ble<'a> {
114 async fn controller_write(&mut self, opcode: Opcode, payload: &[u8]) { 127 async fn controller_write(&mut self, opcode: Opcode, payload: &[u8]) {
115 self.tl_write(opcode.0, payload).await; 128 self.tl_write(opcode.0, payload).await;
116 } 129 }
117 130
131 #[allow(invalid_reference_casting)]
118 async fn controller_read_into(&self, buf: &mut [u8]) { 132 async fn controller_read_into(&self, buf: &mut [u8]) {
119 let evt_box = self.tl_read().await; 133 // A complete hack since I cannot update the trait
134 let s = unsafe { &mut *(self as *const _ as *mut Ble) };
135
136 let evt_box = s.tl_read().await;
120 let evt_serial = evt_box.serial(); 137 let evt_serial = evt_box.serial();
121 138
122 buf[..evt_serial.len()].copy_from_slice(evt_serial); 139 buf[..evt_serial.len()].copy_from_slice(evt_serial);