diff options
| author | xoviat <[email protected]> | 2023-06-16 20:15:03 -0500 |
|---|---|---|
| committer | xoviat <[email protected]> | 2023-06-16 20:15:03 -0500 |
| commit | e1161dfc80e583719bf486d112fa84c948b71fc1 (patch) | |
| tree | 791f00605c9a2d68b3c7c98acd7ab8c660ee64a8 | |
| parent | af451b5462b4cbfaab6ac3ffe56ec9e981f460f7 (diff) | |
stm32/wpan: improve linked list ergonomics
| -rw-r--r-- | embassy-stm32-wpan/src/ble.rs | 27 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/cmd.rs | 19 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mm.rs | 11 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/rc.rs | 8 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/shci.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/sys.rs | 30 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/unsafe_linked_list.rs | 28 | ||||
| -rw-r--r-- | tests/stm32/src/bin/tl_mbox.rs | 5 |
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 @@ | |||
| 1 | use core::mem::MaybeUninit; | ||
| 2 | |||
| 1 | use embassy_stm32::ipcc::Ipcc; | 3 | use embassy_stm32::ipcc::Ipcc; |
| 2 | 4 | ||
| 3 | use crate::cmd::{CmdPacket, CmdSerial}; | 5 | use crate::cmd::CmdPacket; |
| 4 | use crate::consts::TlPacketType; | 6 | use crate::consts::TlPacketType; |
| 5 | use crate::evt::EvtBox; | 7 | use crate::evt::EvtBox; |
| 6 | use crate::tables::BleTable; | 8 | use crate::tables::BleTable; |
| @@ -14,6 +16,11 @@ pub struct Ble; | |||
| 14 | impl Ble { | 16 | impl 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 @@ | |||
| 1 | use core::ptr; | ||
| 2 | |||
| 3 | use crate::consts::TlPacketType; | ||
| 1 | use crate::evt::{EvtPacket, EvtSerial}; | 4 | use crate::evt::{EvtPacket, EvtSerial}; |
| 2 | use crate::{PacketHeader, TL_EVT_HEADER_SIZE}; | 5 | use crate::{PacketHeader, TL_EVT_HEADER_SIZE}; |
| 3 | 6 | ||
| @@ -42,6 +45,22 @@ pub struct CmdPacket { | |||
| 42 | } | 45 | } |
| 43 | 46 | ||
| 44 | impl CmdPacket { | 47 | impl 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; | |||
| 7 | use crate::unsafe_linked_list::LinkedListNode; | 7 | use crate::unsafe_linked_list::LinkedListNode; |
| 8 | use crate::{ | 8 | use 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 | ||
| 13 | pub(super) struct MemoryManager; | 13 | pub(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 @@ | |||
| 1 | use crate::ble::Ble; | 1 | use crate::ble::Ble; |
| 2 | use crate::consts::TlPacketType; | 2 | use crate::consts::TlPacketType; |
| 3 | use crate::{shci, TlMbox, STATE}; | 3 | use crate::{TlMbox, STATE}; |
| 4 | 4 | ||
| 5 | pub struct RadioCoprocessor<'d> { | 5 | pub 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 @@ | |||
| 1 | use core::{mem, slice}; | 1 | use core::{mem, slice}; |
| 2 | 2 | ||
| 3 | use super::cmd::CmdPacket; | 3 | use super::{TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE}; |
| 4 | use super::consts::TlPacketType; | ||
| 5 | use super::{sys, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE}; | ||
| 6 | 4 | ||
| 7 | pub const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66; | 5 | pub 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 @@ | |||
| 1 | use core::ptr; | 1 | use core::mem::MaybeUninit; |
| 2 | use core::sync::atomic::{compiler_fence, Ordering}; | 2 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 3 | 3 | ||
| 4 | use embassy_stm32::ipcc::Ipcc; | 4 | use embassy_stm32::ipcc::Ipcc; |
| 5 | 5 | ||
| 6 | use crate::cmd::{CmdPacket, CmdSerial, CmdSerialStub}; | 6 | use crate::cmd::{CmdPacket, CmdSerial}; |
| 7 | use crate::consts::TlPacketType; | 7 | use crate::consts::TlPacketType; |
| 8 | use crate::evt::{CcEvt, EvtBox, EvtSerial}; | 8 | use crate::evt::{CcEvt, EvtBox, EvtSerial}; |
| 9 | use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT}; | 9 | use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT}; |
| @@ -16,6 +16,11 @@ pub struct Sys; | |||
| 16 | impl Sys { | 16 | impl 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::*; | |||
| 10 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 11 | use embassy_stm32::bind_interrupts; | 11 | use embassy_stm32::bind_interrupts; |
| 12 | use embassy_stm32::ipcc::Config; | 12 | use embassy_stm32::ipcc::Config; |
| 13 | use embassy_stm32_wpan::ble::Ble; | ||
| 13 | use embassy_stm32_wpan::rc::RadioCoprocessor; | 14 | use embassy_stm32_wpan::rc::RadioCoprocessor; |
| 14 | use embassy_stm32_wpan::sys::Sys; | 15 | use embassy_stm32_wpan::sys::Sys; |
| 15 | use embassy_stm32_wpan::TlMbox; | 16 | use 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 | ||
