aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32-wpan/src/ble.rs27
-rw-r--r--embassy-stm32-wpan/src/cmd.rs19
-rw-r--r--embassy-stm32-wpan/src/mm.rs11
-rw-r--r--embassy-stm32-wpan/src/rc.rs8
-rw-r--r--embassy-stm32-wpan/src/shci.rs4
-rw-r--r--embassy-stm32-wpan/src/sys.rs30
-rw-r--r--embassy-stm32-wpan/src/unsafe_linked_list.rs28
-rw-r--r--tests/stm32/src/bin/tl_mbox.rs5
8 files changed, 70 insertions, 62 deletions
diff --git a/embassy-stm32-wpan/src/ble.rs b/embassy-stm32-wpan/src/ble.rs
index 46a2f41c4..d8af861ae 100644
--- a/embassy-stm32-wpan/src/ble.rs
+++ b/embassy-stm32-wpan/src/ble.rs
@@ -1,6 +1,8 @@
1use core::mem::MaybeUninit;
2
1use embassy_stm32::ipcc::Ipcc; 3use embassy_stm32::ipcc::Ipcc;
2 4
3use crate::cmd::{CmdPacket, CmdSerial}; 5use crate::cmd::CmdPacket;
4use crate::consts::TlPacketType; 6use crate::consts::TlPacketType;
5use crate::evt::EvtBox; 7use crate::evt::EvtBox;
6use crate::tables::BleTable; 8use crate::tables::BleTable;
@@ -14,6 +16,11 @@ pub struct Ble;
14impl Ble { 16impl Ble {
15 pub(super) fn enable() { 17 pub(super) fn enable() {
16 unsafe { 18 unsafe {
19 // Ensure reproducible behavior
20 BLE_CMD_BUFFER
21 .as_mut_ptr()
22 .write_volatile(MaybeUninit::zeroed().assume_init());
23
17 LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); 24 LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr());
18 25
19 TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable { 26 TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable {
@@ -29,11 +36,8 @@ impl Ble {
29 36
30 pub(super) fn evt_handler() { 37 pub(super) fn evt_handler() {
31 unsafe { 38 unsafe {
32 while !LinkedListNode::is_empty(EVT_QUEUE.as_mut_ptr()) { 39 while let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) {
33 let node_ptr = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()); 40 let event = EvtBox::new(node_ptr.cast());
34
35 let event = node_ptr.cast();
36 let event = EvtBox::new(event);
37 41
38 EVT_CHANNEL.try_send(event).unwrap(); 42 EVT_CHANNEL.try_send(event).unwrap();
39 } 43 }
@@ -48,18 +52,11 @@ impl Ble {
48 // TODO: ACL data ack to the user 52 // TODO: ACL data ack to the user
49 } 53 }
50 54
51 pub fn send_cmd(buf: &[u8]) { 55 pub fn send_cmd(opcode: u16, payload: &[u8]) {
52 debug!("writing ble cmd"); 56 debug!("writing ble cmd");
53 57
54 unsafe { 58 unsafe {
55 let pcmd_buffer: *mut CmdPacket = BLE_CMD_BUFFER.as_mut_ptr(); 59 CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload);
56 let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmdserial;
57 let pcmd_serial_buf: *mut u8 = pcmd_serial.cast();
58
59 core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len());
60
61 let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer;
62 cmd_packet.cmdserial.ty = TlPacketType::BleCmd as u8;
63 } 60 }
64 61
65 Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL); 62 Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL);
diff --git a/embassy-stm32-wpan/src/cmd.rs b/embassy-stm32-wpan/src/cmd.rs
index a023201ba..581e5019b 100644
--- a/embassy-stm32-wpan/src/cmd.rs
+++ b/embassy-stm32-wpan/src/cmd.rs
@@ -1,3 +1,6 @@
1use core::ptr;
2
3use crate::consts::TlPacketType;
1use crate::evt::{EvtPacket, EvtSerial}; 4use crate::evt::{EvtPacket, EvtSerial};
2use crate::{PacketHeader, TL_EVT_HEADER_SIZE}; 5use crate::{PacketHeader, TL_EVT_HEADER_SIZE};
3 6
@@ -42,6 +45,22 @@ pub struct CmdPacket {
42} 45}
43 46
44impl CmdPacket { 47impl CmdPacket {
48 pub unsafe fn write_into(cmd_buf: *mut CmdPacket, packet_type: TlPacketType, cmd_code: u16, payload: &[u8]) {
49 let p_cmd_serial = &mut (*cmd_buf).cmdserial as *mut _ as *mut CmdSerialStub;
50 let p_payload = &mut (*cmd_buf).cmdserial.cmd.payload as *mut _;
51
52 ptr::write_volatile(
53 p_cmd_serial,
54 CmdSerialStub {
55 ty: packet_type as u8,
56 cmd_code: cmd_code,
57 payload_len: payload.len() as u8,
58 },
59 );
60
61 ptr::copy_nonoverlapping(payload as *const _ as *const u8, p_payload, payload.len());
62 }
63
45 /// Writes an underlying CmdPacket into the provided buffer. 64 /// Writes an underlying CmdPacket into the provided buffer.
46 /// Returns a number of bytes that were written. 65 /// Returns a number of bytes that were written.
47 /// Returns an error if event kind is unknown or if provided buffer size is not enough. 66 /// Returns an error if event kind is unknown or if provided buffer size is not enough.
diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs
index 06063b89a..1ea6edeff 100644
--- a/embassy-stm32-wpan/src/mm.rs
+++ b/embassy-stm32-wpan/src/mm.rs
@@ -7,7 +7,7 @@ use crate::tables::MemManagerTable;
7use crate::unsafe_linked_list::LinkedListNode; 7use crate::unsafe_linked_list::LinkedListNode;
8use crate::{ 8use crate::{
9 channels, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF, 9 channels, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF,
10 TL_MEM_MANAGER_TABLE, TL_REF_TABLE, 10 TL_MEM_MANAGER_TABLE,
11}; 11};
12 12
13pub(super) struct MemoryManager; 13pub(super) struct MemoryManager;
@@ -51,13 +51,8 @@ impl MemoryManager {
51 /// gives free event buffers back to CPU2 from local buffer queue 51 /// gives free event buffers back to CPU2 from local buffer queue
52 pub fn send_free_buf() { 52 pub fn send_free_buf() {
53 unsafe { 53 unsafe {
54 while !LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { 54 while let Some(node_ptr) = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) {
55 let node_ptr = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); 55 LinkedListNode::insert_head(FREE_BUF_QUEUE.as_mut_ptr(), node_ptr);
56
57 LinkedListNode::insert_tail(
58 (*(*TL_REF_TABLE.as_ptr()).mem_manager_table).pevt_free_buffer_queue,
59 node_ptr,
60 );
61 } 56 }
62 } 57 }
63 } 58 }
diff --git a/embassy-stm32-wpan/src/rc.rs b/embassy-stm32-wpan/src/rc.rs
index a217aa224..e67350f79 100644
--- a/embassy-stm32-wpan/src/rc.rs
+++ b/embassy-stm32-wpan/src/rc.rs
@@ -1,6 +1,6 @@
1use crate::ble::Ble; 1use crate::ble::Ble;
2use crate::consts::TlPacketType; 2use crate::consts::TlPacketType;
3use crate::{shci, TlMbox, STATE}; 3use crate::{TlMbox, STATE};
4 4
5pub struct RadioCoprocessor<'d> { 5pub struct RadioCoprocessor<'d> {
6 mbox: TlMbox<'d>, 6 mbox: TlMbox<'d>,
@@ -15,12 +15,12 @@ impl<'d> RadioCoprocessor<'d> {
15 } 15 }
16 } 16 }
17 17
18 pub fn write(&self, buf: &[u8]) { 18 pub fn write(&self, opcode: u16, buf: &[u8]) {
19 let cmd_code = buf[0]; 19 let cmd_code = buf[0];
20 let cmd = TlPacketType::try_from(cmd_code).unwrap(); 20 let cmd = TlPacketType::try_from(cmd_code).unwrap();
21 21
22 match &cmd { 22 match &cmd {
23 TlPacketType::BleCmd => Ble::send_cmd(buf), 23 TlPacketType::BleCmd => Ble::send_cmd(opcode, buf),
24 _ => todo!(), 24 _ => todo!(),
25 } 25 }
26 } 26 }
@@ -30,8 +30,6 @@ impl<'d> RadioCoprocessor<'d> {
30 STATE.wait().await; 30 STATE.wait().await;
31 31
32 while let Some(evt) = self.mbox.dequeue_event() { 32 while let Some(evt) = self.mbox.dequeue_event() {
33 let event = evt.evt();
34
35 evt.write(&mut self.rx_buf).unwrap(); 33 evt.write(&mut self.rx_buf).unwrap();
36 } 34 }
37 35
diff --git a/embassy-stm32-wpan/src/shci.rs b/embassy-stm32-wpan/src/shci.rs
index 6e58a7156..cdf027d5e 100644
--- a/embassy-stm32-wpan/src/shci.rs
+++ b/embassy-stm32-wpan/src/shci.rs
@@ -1,8 +1,6 @@
1use core::{mem, slice}; 1use core::{mem, slice};
2 2
3use super::cmd::CmdPacket; 3use super::{TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE};
4use super::consts::TlPacketType;
5use super::{sys, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE};
6 4
7pub const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66; 5pub const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66;
8 6
diff --git a/embassy-stm32-wpan/src/sys.rs b/embassy-stm32-wpan/src/sys.rs
index 76f65cbd8..fb247f276 100644
--- a/embassy-stm32-wpan/src/sys.rs
+++ b/embassy-stm32-wpan/src/sys.rs
@@ -1,9 +1,9 @@
1use core::ptr; 1use core::mem::MaybeUninit;
2use core::sync::atomic::{compiler_fence, Ordering}; 2use core::sync::atomic::{compiler_fence, Ordering};
3 3
4use embassy_stm32::ipcc::Ipcc; 4use embassy_stm32::ipcc::Ipcc;
5 5
6use crate::cmd::{CmdPacket, CmdSerial, CmdSerialStub}; 6use crate::cmd::{CmdPacket, CmdSerial};
7use crate::consts::TlPacketType; 7use crate::consts::TlPacketType;
8use crate::evt::{CcEvt, EvtBox, EvtSerial}; 8use crate::evt::{CcEvt, EvtBox, EvtSerial};
9use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT}; 9use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT};
@@ -16,6 +16,11 @@ pub struct Sys;
16impl Sys { 16impl Sys {
17 pub fn enable() { 17 pub fn enable() {
18 unsafe { 18 unsafe {
19 // Ensure reproducible behavior
20 SYS_CMD_BUF
21 .as_mut_ptr()
22 .write_volatile(MaybeUninit::zeroed().assume_init());
23
19 LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); 24 LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr());
20 25
21 TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { 26 TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable {
@@ -50,11 +55,8 @@ impl Sys {
50 55
51 pub fn evt_handler() { 56 pub fn evt_handler() {
52 unsafe { 57 unsafe {
53 while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { 58 while let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) {
54 let node_ptr = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); 59 let event = EvtBox::new(node_ptr.cast());
55
56 let event = node_ptr.cast();
57 let event = EvtBox::new(event);
58 60
59 EVT_CHANNEL.try_send(event).unwrap(); 61 EVT_CHANNEL.try_send(event).unwrap();
60 } 62 }
@@ -71,19 +73,7 @@ impl Sys {
71 73
72 pub fn send_cmd(opcode: u16, payload: &[u8]) { 74 pub fn send_cmd(opcode: u16, payload: &[u8]) {
73 unsafe { 75 unsafe {
74 let p_cmd_serial = &mut (*SYS_CMD_BUF.as_mut_ptr()).cmdserial as *mut _ as *mut CmdSerialStub; 76 CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode, payload);
75 let p_payload = &mut (*SYS_CMD_BUF.as_mut_ptr()).cmdserial.cmd.payload as *mut _;
76
77 ptr::write_volatile(
78 p_cmd_serial,
79 CmdSerialStub {
80 ty: TlPacketType::SysCmd as u8,
81 cmd_code: opcode,
82 payload_len: payload.len() as u8,
83 },
84 );
85
86 ptr::copy_nonoverlapping(payload as *const _ as *const u8, p_payload, payload.len());
87 } 77 }
88 78
89 compiler_fence(Ordering::SeqCst); 79 compiler_fence(Ordering::SeqCst);
diff --git a/embassy-stm32-wpan/src/unsafe_linked_list.rs b/embassy-stm32-wpan/src/unsafe_linked_list.rs
index a312178b3..5b210aac4 100644
--- a/embassy-stm32-wpan/src/unsafe_linked_list.rs
+++ b/embassy-stm32-wpan/src/unsafe_linked_list.rs
@@ -139,28 +139,36 @@ impl LinkedListNode {
139 } 139 }
140 140
141 /// Remove `list_head` and return a pointer to the `node`. 141 /// Remove `list_head` and return a pointer to the `node`.
142 pub unsafe fn remove_head(mut p_list_head: *mut LinkedListNode) -> *mut LinkedListNode { 142 pub unsafe fn remove_head(mut p_list_head: *mut LinkedListNode) -> Option<*mut LinkedListNode> {
143 interrupt::free(|_| { 143 interrupt::free(|_| {
144 let list_head = ptr::read_volatile(p_list_head); 144 let list_head = ptr::read_volatile(p_list_head);
145 145
146 // Allowed because a removed node is not seen by another core 146 if list_head.next == p_list_head {
147 let p_node = list_head.next; 147 None
148 Self::remove_node(p_node); 148 } else {
149 // Allowed because a removed node is not seen by another core
150 let p_node = list_head.next;
151 Self::remove_node(p_node);
149 152
150 p_node 153 Some(p_node)
154 }
151 }) 155 })
152 } 156 }
153 157
154 /// Remove `list_tail` and return a pointer to the `node`. 158 /// Remove `list_tail` and return a pointer to the `node`.
155 pub unsafe fn remove_tail(mut p_list_tail: *mut LinkedListNode) -> *mut LinkedListNode { 159 pub unsafe fn remove_tail(mut p_list_tail: *mut LinkedListNode) -> Option<*mut LinkedListNode> {
156 interrupt::free(|_| { 160 interrupt::free(|_| {
157 let list_tail = ptr::read_volatile(p_list_tail); 161 let list_tail = ptr::read_volatile(p_list_tail);
158 162
159 // Allowed because a removed node is not seen by another core 163 if list_tail.prev == p_list_tail {
160 let p_node = list_tail.prev; 164 None
161 Self::remove_node(p_node); 165 } else {
166 // Allowed because a removed node is not seen by another core
167 let p_node = list_tail.prev;
168 Self::remove_node(p_node);
162 169
163 p_node 170 Some(p_node)
171 }
164 }) 172 })
165 } 173 }
166 174
diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs
index 5e7d11ef5..5a2309263 100644
--- a/tests/stm32/src/bin/tl_mbox.rs
+++ b/tests/stm32/src/bin/tl_mbox.rs
@@ -10,6 +10,7 @@ use common::*;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_stm32::bind_interrupts; 11use embassy_stm32::bind_interrupts;
12use embassy_stm32::ipcc::Config; 12use embassy_stm32::ipcc::Config;
13use embassy_stm32_wpan::ble::Ble;
13use embassy_stm32_wpan::rc::RadioCoprocessor; 14use embassy_stm32_wpan::rc::RadioCoprocessor;
14use embassy_stm32_wpan::sys::Sys; 15use embassy_stm32_wpan::sys::Sys;
15use embassy_stm32_wpan::TlMbox; 16use embassy_stm32_wpan::TlMbox;
@@ -59,7 +60,9 @@ async fn main(_spawner: Spawner) {
59 60
60 Sys::shci_ble_init(Default::default()); 61 Sys::shci_ble_init(Default::default());
61 62
62 rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]); 63 // rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]);
64 Ble::send_cmd(0x0c, &[]);
65
63 let response = rc.read().await; 66 let response = rc.read().await;
64 info!("ble reset rsp {}", response); 67 info!("ble reset rsp {}", response);
65 68