stm32/wpan: improve linked list ergonomics
This commit is contained in:
parent
af451b5462
commit
e1161dfc80
8 changed files with 70 additions and 62 deletions
|
@ -1,6 +1,8 @@
|
||||||
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
use embassy_stm32::ipcc::Ipcc;
|
use embassy_stm32::ipcc::Ipcc;
|
||||||
|
|
||||||
use crate::cmd::{CmdPacket, CmdSerial};
|
use crate::cmd::CmdPacket;
|
||||||
use crate::consts::TlPacketType;
|
use crate::consts::TlPacketType;
|
||||||
use crate::evt::EvtBox;
|
use crate::evt::EvtBox;
|
||||||
use crate::tables::BleTable;
|
use crate::tables::BleTable;
|
||||||
|
@ -14,6 +16,11 @@ pub struct Ble;
|
||||||
impl Ble {
|
impl Ble {
|
||||||
pub(super) fn enable() {
|
pub(super) fn enable() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
// Ensure reproducible behavior
|
||||||
|
BLE_CMD_BUFFER
|
||||||
|
.as_mut_ptr()
|
||||||
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
||||||
|
|
||||||
LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr());
|
LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr());
|
||||||
|
|
||||||
TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable {
|
TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable {
|
||||||
|
@ -29,11 +36,8 @@ impl Ble {
|
||||||
|
|
||||||
pub(super) fn evt_handler() {
|
pub(super) fn evt_handler() {
|
||||||
unsafe {
|
unsafe {
|
||||||
while !LinkedListNode::is_empty(EVT_QUEUE.as_mut_ptr()) {
|
while let Some(node_ptr) = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr()) {
|
||||||
let node_ptr = LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr());
|
let event = EvtBox::new(node_ptr.cast());
|
||||||
|
|
||||||
let event = node_ptr.cast();
|
|
||||||
let event = EvtBox::new(event);
|
|
||||||
|
|
||||||
EVT_CHANNEL.try_send(event).unwrap();
|
EVT_CHANNEL.try_send(event).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -48,18 +52,11 @@ impl Ble {
|
||||||
// TODO: ACL data ack to the user
|
// TODO: ACL data ack to the user
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_cmd(buf: &[u8]) {
|
pub fn send_cmd(opcode: u16, payload: &[u8]) {
|
||||||
debug!("writing ble cmd");
|
debug!("writing ble cmd");
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let pcmd_buffer: *mut CmdPacket = BLE_CMD_BUFFER.as_mut_ptr();
|
CmdPacket::write_into(BLE_CMD_BUFFER.as_mut_ptr(), TlPacketType::BleCmd, opcode, payload);
|
||||||
let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmdserial;
|
|
||||||
let pcmd_serial_buf: *mut u8 = pcmd_serial.cast();
|
|
||||||
|
|
||||||
core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len());
|
|
||||||
|
|
||||||
let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer;
|
|
||||||
cmd_packet.cmdserial.ty = TlPacketType::BleCmd as u8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL);
|
Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL);
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
use core::ptr;
|
||||||
|
|
||||||
|
use crate::consts::TlPacketType;
|
||||||
use crate::evt::{EvtPacket, EvtSerial};
|
use crate::evt::{EvtPacket, EvtSerial};
|
||||||
use crate::{PacketHeader, TL_EVT_HEADER_SIZE};
|
use crate::{PacketHeader, TL_EVT_HEADER_SIZE};
|
||||||
|
|
||||||
|
@ -42,6 +45,22 @@ pub struct CmdPacket {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CmdPacket {
|
impl CmdPacket {
|
||||||
|
pub unsafe fn write_into(cmd_buf: *mut CmdPacket, packet_type: TlPacketType, cmd_code: u16, payload: &[u8]) {
|
||||||
|
let p_cmd_serial = &mut (*cmd_buf).cmdserial as *mut _ as *mut CmdSerialStub;
|
||||||
|
let p_payload = &mut (*cmd_buf).cmdserial.cmd.payload as *mut _;
|
||||||
|
|
||||||
|
ptr::write_volatile(
|
||||||
|
p_cmd_serial,
|
||||||
|
CmdSerialStub {
|
||||||
|
ty: packet_type as u8,
|
||||||
|
cmd_code: cmd_code,
|
||||||
|
payload_len: payload.len() as u8,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ptr::copy_nonoverlapping(payload as *const _ as *const u8, p_payload, payload.len());
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes an underlying CmdPacket into the provided buffer.
|
/// Writes an underlying CmdPacket into the provided buffer.
|
||||||
/// Returns a number of bytes that were written.
|
/// Returns a number of bytes that were written.
|
||||||
/// Returns an error if event kind is unknown or if provided buffer size is not enough.
|
/// Returns an error if event kind is unknown or if provided buffer size is not enough.
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::tables::MemManagerTable;
|
||||||
use crate::unsafe_linked_list::LinkedListNode;
|
use crate::unsafe_linked_list::LinkedListNode;
|
||||||
use crate::{
|
use crate::{
|
||||||
channels, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF,
|
channels, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF,
|
||||||
TL_MEM_MANAGER_TABLE, TL_REF_TABLE,
|
TL_MEM_MANAGER_TABLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) struct MemoryManager;
|
pub(super) struct MemoryManager;
|
||||||
|
@ -51,13 +51,8 @@ impl MemoryManager {
|
||||||
/// gives free event buffers back to CPU2 from local buffer queue
|
/// gives free event buffers back to CPU2 from local buffer queue
|
||||||
pub fn send_free_buf() {
|
pub fn send_free_buf() {
|
||||||
unsafe {
|
unsafe {
|
||||||
while !LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) {
|
while let Some(node_ptr) = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) {
|
||||||
let node_ptr = LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr());
|
LinkedListNode::insert_head(FREE_BUF_QUEUE.as_mut_ptr(), node_ptr);
|
||||||
|
|
||||||
LinkedListNode::insert_tail(
|
|
||||||
(*(*TL_REF_TABLE.as_ptr()).mem_manager_table).pevt_free_buffer_queue,
|
|
||||||
node_ptr,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::ble::Ble;
|
use crate::ble::Ble;
|
||||||
use crate::consts::TlPacketType;
|
use crate::consts::TlPacketType;
|
||||||
use crate::{shci, TlMbox, STATE};
|
use crate::{TlMbox, STATE};
|
||||||
|
|
||||||
pub struct RadioCoprocessor<'d> {
|
pub struct RadioCoprocessor<'d> {
|
||||||
mbox: TlMbox<'d>,
|
mbox: TlMbox<'d>,
|
||||||
|
@ -15,12 +15,12 @@ impl<'d> RadioCoprocessor<'d> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&self, buf: &[u8]) {
|
pub fn write(&self, opcode: u16, buf: &[u8]) {
|
||||||
let cmd_code = buf[0];
|
let cmd_code = buf[0];
|
||||||
let cmd = TlPacketType::try_from(cmd_code).unwrap();
|
let cmd = TlPacketType::try_from(cmd_code).unwrap();
|
||||||
|
|
||||||
match &cmd {
|
match &cmd {
|
||||||
TlPacketType::BleCmd => Ble::send_cmd(buf),
|
TlPacketType::BleCmd => Ble::send_cmd(opcode, buf),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,6 @@ impl<'d> RadioCoprocessor<'d> {
|
||||||
STATE.wait().await;
|
STATE.wait().await;
|
||||||
|
|
||||||
while let Some(evt) = self.mbox.dequeue_event() {
|
while let Some(evt) = self.mbox.dequeue_event() {
|
||||||
let event = evt.evt();
|
|
||||||
|
|
||||||
evt.write(&mut self.rx_buf).unwrap();
|
evt.write(&mut self.rx_buf).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use core::{mem, slice};
|
use core::{mem, slice};
|
||||||
|
|
||||||
use super::cmd::CmdPacket;
|
use super::{TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE};
|
||||||
use super::consts::TlPacketType;
|
|
||||||
use super::{sys, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE};
|
|
||||||
|
|
||||||
pub const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66;
|
pub const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use core::ptr;
|
use core::mem::MaybeUninit;
|
||||||
use core::sync::atomic::{compiler_fence, Ordering};
|
use core::sync::atomic::{compiler_fence, Ordering};
|
||||||
|
|
||||||
use embassy_stm32::ipcc::Ipcc;
|
use embassy_stm32::ipcc::Ipcc;
|
||||||
|
|
||||||
use crate::cmd::{CmdPacket, CmdSerial, CmdSerialStub};
|
use crate::cmd::{CmdPacket, CmdSerial};
|
||||||
use crate::consts::TlPacketType;
|
use crate::consts::TlPacketType;
|
||||||
use crate::evt::{CcEvt, EvtBox, EvtSerial};
|
use crate::evt::{CcEvt, EvtBox, EvtSerial};
|
||||||
use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT};
|
use crate::shci::{ShciBleInitCmdParam, SCHI_OPCODE_BLE_INIT};
|
||||||
|
@ -16,6 +16,11 @@ pub struct Sys;
|
||||||
impl Sys {
|
impl Sys {
|
||||||
pub fn enable() {
|
pub fn enable() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
// Ensure reproducible behavior
|
||||||
|
SYS_CMD_BUF
|
||||||
|
.as_mut_ptr()
|
||||||
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
||||||
|
|
||||||
LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr());
|
LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr());
|
||||||
|
|
||||||
TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable {
|
TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable {
|
||||||
|
@ -50,11 +55,8 @@ impl Sys {
|
||||||
|
|
||||||
pub fn evt_handler() {
|
pub fn evt_handler() {
|
||||||
unsafe {
|
unsafe {
|
||||||
while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) {
|
while let Some(node_ptr) = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr()) {
|
||||||
let node_ptr = LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr());
|
let event = EvtBox::new(node_ptr.cast());
|
||||||
|
|
||||||
let event = node_ptr.cast();
|
|
||||||
let event = EvtBox::new(event);
|
|
||||||
|
|
||||||
EVT_CHANNEL.try_send(event).unwrap();
|
EVT_CHANNEL.try_send(event).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -71,19 +73,7 @@ impl Sys {
|
||||||
|
|
||||||
pub fn send_cmd(opcode: u16, payload: &[u8]) {
|
pub fn send_cmd(opcode: u16, payload: &[u8]) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let p_cmd_serial = &mut (*SYS_CMD_BUF.as_mut_ptr()).cmdserial as *mut _ as *mut CmdSerialStub;
|
CmdPacket::write_into(SYS_CMD_BUF.as_mut_ptr(), TlPacketType::SysCmd, opcode, payload);
|
||||||
let p_payload = &mut (*SYS_CMD_BUF.as_mut_ptr()).cmdserial.cmd.payload as *mut _;
|
|
||||||
|
|
||||||
ptr::write_volatile(
|
|
||||||
p_cmd_serial,
|
|
||||||
CmdSerialStub {
|
|
||||||
ty: TlPacketType::SysCmd as u8,
|
|
||||||
cmd_code: opcode,
|
|
||||||
payload_len: payload.len() as u8,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
ptr::copy_nonoverlapping(payload as *const _ as *const u8, p_payload, payload.len());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
|
@ -139,28 +139,36 @@ impl LinkedListNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove `list_head` and return a pointer to the `node`.
|
/// Remove `list_head` and return a pointer to the `node`.
|
||||||
pub unsafe fn remove_head(mut p_list_head: *mut LinkedListNode) -> *mut LinkedListNode {
|
pub unsafe fn remove_head(mut p_list_head: *mut LinkedListNode) -> Option<*mut LinkedListNode> {
|
||||||
interrupt::free(|_| {
|
interrupt::free(|_| {
|
||||||
let list_head = ptr::read_volatile(p_list_head);
|
let list_head = ptr::read_volatile(p_list_head);
|
||||||
|
|
||||||
|
if list_head.next == p_list_head {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
// Allowed because a removed node is not seen by another core
|
// Allowed because a removed node is not seen by another core
|
||||||
let p_node = list_head.next;
|
let p_node = list_head.next;
|
||||||
Self::remove_node(p_node);
|
Self::remove_node(p_node);
|
||||||
|
|
||||||
p_node
|
Some(p_node)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove `list_tail` and return a pointer to the `node`.
|
/// Remove `list_tail` and return a pointer to the `node`.
|
||||||
pub unsafe fn remove_tail(mut p_list_tail: *mut LinkedListNode) -> *mut LinkedListNode {
|
pub unsafe fn remove_tail(mut p_list_tail: *mut LinkedListNode) -> Option<*mut LinkedListNode> {
|
||||||
interrupt::free(|_| {
|
interrupt::free(|_| {
|
||||||
let list_tail = ptr::read_volatile(p_list_tail);
|
let list_tail = ptr::read_volatile(p_list_tail);
|
||||||
|
|
||||||
|
if list_tail.prev == p_list_tail {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
// Allowed because a removed node is not seen by another core
|
// Allowed because a removed node is not seen by another core
|
||||||
let p_node = list_tail.prev;
|
let p_node = list_tail.prev;
|
||||||
Self::remove_node(p_node);
|
Self::remove_node(p_node);
|
||||||
|
|
||||||
p_node
|
Some(p_node)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ use common::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::bind_interrupts;
|
use embassy_stm32::bind_interrupts;
|
||||||
use embassy_stm32::ipcc::Config;
|
use embassy_stm32::ipcc::Config;
|
||||||
|
use embassy_stm32_wpan::ble::Ble;
|
||||||
use embassy_stm32_wpan::rc::RadioCoprocessor;
|
use embassy_stm32_wpan::rc::RadioCoprocessor;
|
||||||
use embassy_stm32_wpan::sys::Sys;
|
use embassy_stm32_wpan::sys::Sys;
|
||||||
use embassy_stm32_wpan::TlMbox;
|
use embassy_stm32_wpan::TlMbox;
|
||||||
|
@ -59,7 +60,9 @@ async fn main(_spawner: Spawner) {
|
||||||
|
|
||||||
Sys::shci_ble_init(Default::default());
|
Sys::shci_ble_init(Default::default());
|
||||||
|
|
||||||
rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]);
|
// rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]);
|
||||||
|
Ble::send_cmd(0x0c, &[]);
|
||||||
|
|
||||||
let response = rc.read().await;
|
let response = rc.read().await;
|
||||||
info!("ble reset rsp {}", response);
|
info!("ble reset rsp {}", response);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue