diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2023-05-23 01:15:22 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-05-23 01:15:22 +0000 |
| commit | 1fdde8f03fc8b98c7fdb91a94e2dfd47bcbc24cb (patch) | |
| tree | b28d26b4a54ecccce2de498e5106fc55be631061 /embassy-stm32 | |
| parent | ab7d129e152a9450b2a6445397365bcb3a3ce183 (diff) | |
| parent | 64092169e3133b572626c1efa106963139a63b3f (diff) | |
Merge #1457
1457: TL Mbox read and write for stm32wb r=xoviat a=OueslatiGhaith
Hello,
This pull request is related to #1397 and #1401, inspired by #24, built upon the work done in #1405 and #1424, and was tested on an stm32wb55rg.
This pull request aims to add read and write functionality to the TL mailbox for stm32wb microcontrollers
Co-authored-by: goueslati <[email protected]>
Co-authored-by: xoviat <[email protected]>
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/src/ipcc.rs | 8 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/ble.rs | 50 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/channels.rs | 8 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/consts.rs | 53 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/evt.rs | 131 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/mm.rs | 51 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/mod.rs | 103 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/shci.rs | 101 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/sys.rs | 71 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/unsafe_linked_list.rs | 158 |
10 files changed, 627 insertions, 107 deletions
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs index 903aeca30..2b9caf8e5 100644 --- a/embassy-stm32/src/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs | |||
| @@ -35,6 +35,10 @@ pub struct Ipcc<'d> { | |||
| 35 | 35 | ||
| 36 | impl<'d> Ipcc<'d> { | 36 | impl<'d> Ipcc<'d> { |
| 37 | pub fn new(peri: impl Peripheral<P = IPCC> + 'd, _config: Config) -> Self { | 37 | pub fn new(peri: impl Peripheral<P = IPCC> + 'd, _config: Config) -> Self { |
| 38 | Self::new_inner(peri) | ||
| 39 | } | ||
| 40 | |||
| 41 | pub(crate) fn new_inner(peri: impl Peripheral<P = IPCC> + 'd) -> Self { | ||
| 38 | into_ref!(peri); | 42 | into_ref!(peri); |
| 39 | 43 | ||
| 40 | Self { _peri: peri } | 44 | Self { _peri: peri } |
| @@ -158,6 +162,10 @@ impl<'d> Ipcc<'d> { | |||
| 158 | pub fn is_rx_pending(&self, channel: IpccChannel) -> bool { | 162 | pub fn is_rx_pending(&self, channel: IpccChannel) -> bool { |
| 159 | self.c2_is_active_flag(channel) && self.c1_get_rx_channel(channel) | 163 | self.c2_is_active_flag(channel) && self.c1_get_rx_channel(channel) |
| 160 | } | 164 | } |
| 165 | |||
| 166 | pub fn as_mut_ptr(&self) -> *mut Self { | ||
| 167 | unsafe { &mut core::ptr::read(self) as *mut _ } | ||
| 168 | } | ||
| 161 | } | 169 | } |
| 162 | 170 | ||
| 163 | impl sealed::Instance for crate::peripherals::IPCC { | 171 | impl sealed::Instance for crate::peripherals::IPCC { |
diff --git a/embassy-stm32/src/tl_mbox/ble.rs b/embassy-stm32/src/tl_mbox/ble.rs index a2c0758d1..d8bf14d4f 100644 --- a/embassy-stm32/src/tl_mbox/ble.rs +++ b/embassy-stm32/src/tl_mbox/ble.rs | |||
| @@ -1,15 +1,24 @@ | |||
| 1 | use core::mem::MaybeUninit; | 1 | use core::mem::MaybeUninit; |
| 2 | 2 | ||
| 3 | use super::unsafe_linked_list::LST_init_head; | 3 | use embassy_futures::block_on; |
| 4 | use super::{channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE}; | 4 | |
| 5 | use super::cmd::CmdSerial; | ||
| 6 | use super::consts::TlPacketType; | ||
| 7 | use super::evt::EvtBox; | ||
| 8 | use super::unsafe_linked_list::LinkedListNode; | ||
| 9 | use super::{ | ||
| 10 | channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE, TL_CHANNEL, | ||
| 11 | TL_REF_TABLE, | ||
| 12 | }; | ||
| 5 | use crate::ipcc::Ipcc; | 13 | use crate::ipcc::Ipcc; |
| 14 | use crate::tl_mbox::cmd::CmdPacket; | ||
| 6 | 15 | ||
| 7 | pub struct Ble; | 16 | pub struct Ble; |
| 8 | 17 | ||
| 9 | impl Ble { | 18 | impl Ble { |
| 10 | pub fn new(ipcc: &mut Ipcc) -> Self { | 19 | pub(crate) fn new(ipcc: &mut Ipcc) -> Self { |
| 11 | unsafe { | 20 | unsafe { |
| 12 | LST_init_head(EVT_QUEUE.as_mut_ptr()); | 21 | LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); |
| 13 | 22 | ||
| 14 | TL_BLE_TABLE = MaybeUninit::new(BleTable { | 23 | TL_BLE_TABLE = MaybeUninit::new(BleTable { |
| 15 | pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), | 24 | pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), |
| @@ -23,4 +32,37 @@ impl Ble { | |||
| 23 | 32 | ||
| 24 | Ble | 33 | Ble |
| 25 | } | 34 | } |
| 35 | |||
| 36 | pub(crate) fn evt_handler(ipcc: &mut Ipcc) { | ||
| 37 | unsafe { | ||
| 38 | let mut node_ptr = core::ptr::null_mut(); | ||
| 39 | let node_ptr_ptr: *mut _ = &mut node_ptr; | ||
| 40 | |||
| 41 | while !LinkedListNode::is_empty(EVT_QUEUE.as_mut_ptr()) { | ||
| 42 | LinkedListNode::remove_head(EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); | ||
| 43 | |||
| 44 | let event = node_ptr.cast(); | ||
| 45 | let event = EvtBox::new(event); | ||
| 46 | |||
| 47 | block_on(TL_CHANNEL.send(event)); | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | ipcc.c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL); | ||
| 52 | } | ||
| 53 | |||
| 54 | pub(crate) fn send_cmd(ipcc: &mut Ipcc, buf: &[u8]) { | ||
| 55 | unsafe { | ||
| 56 | let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; | ||
| 57 | let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmd_serial; | ||
| 58 | let pcmd_serial_buf: *mut u8 = pcmd_serial.cast(); | ||
| 59 | |||
| 60 | core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len()); | ||
| 61 | |||
| 62 | let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; | ||
| 63 | cmd_packet.cmd_serial.ty = TlPacketType::BleCmd as u8; | ||
| 64 | } | ||
| 65 | |||
| 66 | ipcc.c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL); | ||
| 67 | } | ||
| 26 | } | 68 | } |
diff --git a/embassy-stm32/src/tl_mbox/channels.rs b/embassy-stm32/src/tl_mbox/channels.rs index 1dde5d61c..aaa6ce177 100644 --- a/embassy-stm32/src/tl_mbox/channels.rs +++ b/embassy-stm32/src/tl_mbox/channels.rs | |||
| @@ -52,9 +52,9 @@ | |||
| 52 | pub mod cpu1 { | 52 | pub mod cpu1 { |
| 53 | use crate::ipcc::IpccChannel; | 53 | use crate::ipcc::IpccChannel; |
| 54 | 54 | ||
| 55 | #[allow(dead_code)] // Not used currently but reserved | 55 | // Not used currently but reserved |
| 56 | pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1; | 56 | pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1; |
| 57 | #[allow(dead_code)] // Not used currently but reserved | 57 | // Not used currently but reserved |
| 58 | pub const IPCC_SYSTEM_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel2; | 58 | pub const IPCC_SYSTEM_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel2; |
| 59 | #[allow(dead_code)] // Not used currently but reserved | 59 | #[allow(dead_code)] // Not used currently but reserved |
| 60 | pub const IPCC_THREAD_OT_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; | 60 | pub const IPCC_THREAD_OT_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; |
| @@ -62,7 +62,7 @@ pub mod cpu1 { | |||
| 62 | pub const IPCC_ZIGBEE_CMD_APPLI_CHANNEL: IpccChannel = IpccChannel::Channel3; | 62 | pub const IPCC_ZIGBEE_CMD_APPLI_CHANNEL: IpccChannel = IpccChannel::Channel3; |
| 63 | #[allow(dead_code)] // Not used currently but reserved | 63 | #[allow(dead_code)] // Not used currently but reserved |
| 64 | pub const IPCC_MAC_802_15_4_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; | 64 | pub const IPCC_MAC_802_15_4_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; |
| 65 | #[allow(dead_code)] // Not used currently but reserved | 65 | // Not used currently but reserved |
| 66 | pub const IPCC_MM_RELEASE_BUFFER_CHANNEL: IpccChannel = IpccChannel::Channel4; | 66 | pub const IPCC_MM_RELEASE_BUFFER_CHANNEL: IpccChannel = IpccChannel::Channel4; |
| 67 | #[allow(dead_code)] // Not used currently but reserved | 67 | #[allow(dead_code)] // Not used currently but reserved |
| 68 | pub const IPCC_THREAD_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; | 68 | pub const IPCC_THREAD_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; |
| @@ -88,7 +88,7 @@ pub mod cpu2 { | |||
| 88 | #[allow(dead_code)] // Not used currently but reserved | 88 | #[allow(dead_code)] // Not used currently but reserved |
| 89 | pub const IPCC_LDDTESTS_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; | 89 | pub const IPCC_LDDTESTS_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; |
| 90 | #[allow(dead_code)] // Not used currently but reserved | 90 | #[allow(dead_code)] // Not used currently but reserved |
| 91 | pub const IPCC_BLE_LLDÇM0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; | 91 | pub const IPCC_BLE_LLD_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; |
| 92 | #[allow(dead_code)] // Not used currently but reserved | 92 | #[allow(dead_code)] // Not used currently but reserved |
| 93 | pub const IPCC_TRACES_CHANNEL: IpccChannel = IpccChannel::Channel4; | 93 | pub const IPCC_TRACES_CHANNEL: IpccChannel = IpccChannel::Channel4; |
| 94 | #[allow(dead_code)] // Not used currently but reserved | 94 | #[allow(dead_code)] // Not used currently but reserved |
diff --git a/embassy-stm32/src/tl_mbox/consts.rs b/embassy-stm32/src/tl_mbox/consts.rs new file mode 100644 index 000000000..e16a26cd0 --- /dev/null +++ b/embassy-stm32/src/tl_mbox/consts.rs | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | #[derive(PartialEq)] | ||
| 2 | #[repr(C)] | ||
| 3 | pub enum TlPacketType { | ||
| 4 | BleCmd = 0x01, | ||
| 5 | AclData = 0x02, | ||
| 6 | BleEvt = 0x04, | ||
| 7 | |||
| 8 | OtCmd = 0x08, | ||
| 9 | OtRsp = 0x09, | ||
| 10 | CliCmd = 0x0A, | ||
| 11 | OtNot = 0x0C, | ||
| 12 | OtAck = 0x0D, | ||
| 13 | CliNot = 0x0E, | ||
| 14 | CliAck = 0x0F, | ||
| 15 | |||
| 16 | SysCmd = 0x10, | ||
| 17 | SysRsp = 0x11, | ||
| 18 | SysEvt = 0x12, | ||
| 19 | |||
| 20 | LocCmd = 0x20, | ||
| 21 | LocRsp = 0x21, | ||
| 22 | |||
| 23 | TracesApp = 0x40, | ||
| 24 | TracesWl = 0x41, | ||
| 25 | } | ||
| 26 | |||
| 27 | impl TryFrom<u8> for TlPacketType { | ||
| 28 | type Error = (); | ||
| 29 | |||
| 30 | fn try_from(value: u8) -> Result<Self, Self::Error> { | ||
| 31 | match value { | ||
| 32 | 0x01 => Ok(TlPacketType::BleCmd), | ||
| 33 | 0x02 => Ok(TlPacketType::AclData), | ||
| 34 | 0x04 => Ok(TlPacketType::BleEvt), | ||
| 35 | 0x08 => Ok(TlPacketType::OtCmd), | ||
| 36 | 0x09 => Ok(TlPacketType::OtRsp), | ||
| 37 | 0x0A => Ok(TlPacketType::CliCmd), | ||
| 38 | 0x0C => Ok(TlPacketType::OtNot), | ||
| 39 | 0x0D => Ok(TlPacketType::OtAck), | ||
| 40 | 0x0E => Ok(TlPacketType::CliNot), | ||
| 41 | 0x0F => Ok(TlPacketType::CliAck), | ||
| 42 | 0x10 => Ok(TlPacketType::SysCmd), | ||
| 43 | 0x11 => Ok(TlPacketType::SysRsp), | ||
| 44 | 0x12 => Ok(TlPacketType::SysEvt), | ||
| 45 | 0x20 => Ok(TlPacketType::LocCmd), | ||
| 46 | 0x21 => Ok(TlPacketType::LocRsp), | ||
| 47 | 0x40 => Ok(TlPacketType::TracesApp), | ||
| 48 | 0x41 => Ok(TlPacketType::TracesWl), | ||
| 49 | |||
| 50 | _ => Err(()), | ||
| 51 | } | ||
| 52 | } | ||
| 53 | } | ||
diff --git a/embassy-stm32/src/tl_mbox/evt.rs b/embassy-stm32/src/tl_mbox/evt.rs index 4244db810..770133f29 100644 --- a/embassy-stm32/src/tl_mbox/evt.rs +++ b/embassy-stm32/src/tl_mbox/evt.rs | |||
| @@ -1,3 +1,10 @@ | |||
| 1 | use core::mem::MaybeUninit; | ||
| 2 | |||
| 3 | use super::cmd::{AclDataPacket, AclDataSerial}; | ||
| 4 | use super::consts::TlPacketType; | ||
| 5 | use super::{PacketHeader, TL_EVT_HEADER_SIZE}; | ||
| 6 | use crate::tl_mbox::mm; | ||
| 7 | |||
| 1 | /// the payload of [`Evt`] for a command status event | 8 | /// the payload of [`Evt`] for a command status event |
| 2 | #[derive(Copy, Clone)] | 9 | #[derive(Copy, Clone)] |
| 3 | #[repr(C, packed)] | 10 | #[repr(C, packed)] |
| @@ -6,3 +13,127 @@ pub struct CsEvt { | |||
| 6 | pub num_cmd: u8, | 13 | pub num_cmd: u8, |
| 7 | pub cmd_code: u16, | 14 | pub cmd_code: u16, |
| 8 | } | 15 | } |
| 16 | |||
| 17 | /// the payload of [`Evt`] for a command complete event | ||
| 18 | #[derive(Clone, Copy, Default)] | ||
| 19 | #[repr(C, packed)] | ||
| 20 | pub struct CcEvt { | ||
| 21 | pub num_cmd: u8, | ||
| 22 | pub cmd_code: u8, | ||
| 23 | pub payload: [u8; 1], | ||
| 24 | } | ||
| 25 | |||
| 26 | #[derive(Clone, Copy, Default)] | ||
| 27 | #[repr(C, packed)] | ||
| 28 | pub struct Evt { | ||
| 29 | pub evt_code: u8, | ||
| 30 | pub payload_len: u8, | ||
| 31 | pub payload: [u8; 1], | ||
| 32 | } | ||
| 33 | |||
| 34 | #[derive(Clone, Copy, Default)] | ||
| 35 | #[repr(C, packed)] | ||
| 36 | pub struct EvtSerial { | ||
| 37 | pub kind: u8, | ||
| 38 | pub evt: Evt, | ||
| 39 | } | ||
| 40 | |||
| 41 | /// This format shall be used for all events (asynchronous and command response) reported | ||
| 42 | /// by the CPU2 except for the command response of a system command where the header is not there | ||
| 43 | /// and the format to be used shall be `EvtSerial`. | ||
| 44 | /// | ||
| 45 | /// ### Note: | ||
| 46 | /// Be careful that the asynchronous events reported by the CPU2 on the system channel do | ||
| 47 | /// include the header and shall use `EvtPacket` format. Only the command response format on the | ||
| 48 | /// system channel is different. | ||
| 49 | #[derive(Clone, Copy, Default)] | ||
| 50 | #[repr(C, packed)] | ||
| 51 | pub struct EvtPacket { | ||
| 52 | pub header: PacketHeader, | ||
| 53 | pub evt_serial: EvtSerial, | ||
| 54 | } | ||
| 55 | |||
| 56 | /// Smart pointer to the [`EvtPacket`] that will dispose of it automatically on drop | ||
| 57 | pub struct EvtBox { | ||
| 58 | ptr: *mut EvtPacket, | ||
| 59 | } | ||
| 60 | |||
| 61 | unsafe impl Send for EvtBox {} | ||
| 62 | impl EvtBox { | ||
| 63 | pub(super) fn new(ptr: *mut EvtPacket) -> Self { | ||
| 64 | Self { ptr } | ||
| 65 | } | ||
| 66 | |||
| 67 | /// Copies the event data from inner pointer and returns and event structure | ||
| 68 | pub fn evt(&self) -> EvtPacket { | ||
| 69 | let mut evt = MaybeUninit::uninit(); | ||
| 70 | unsafe { | ||
| 71 | self.ptr.copy_to(evt.as_mut_ptr(), 1); | ||
| 72 | evt.assume_init() | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | /// Returns the size of a buffer required to hold this event | ||
| 77 | pub fn size(&self) -> Result<usize, ()> { | ||
| 78 | unsafe { | ||
| 79 | let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; | ||
| 80 | |||
| 81 | if evt_kind == TlPacketType::AclData { | ||
| 82 | let acl_data: *const AclDataPacket = self.ptr.cast(); | ||
| 83 | let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; | ||
| 84 | |||
| 85 | Ok((*acl_serial).length as usize + 5) | ||
| 86 | } else { | ||
| 87 | let evt_data: *const EvtPacket = self.ptr.cast(); | ||
| 88 | let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; | ||
| 89 | |||
| 90 | Ok((*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE) | ||
| 91 | } | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | /// writes an underlying [`EvtPacket`] into the provided buffer. Returns the number of bytes that were | ||
| 96 | /// written. Returns an error if event kind is unkown or if provided buffer size is not enough | ||
| 97 | pub fn copy_into_slice(&self, buf: &mut [u8]) -> Result<usize, ()> { | ||
| 98 | unsafe { | ||
| 99 | let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; | ||
| 100 | |||
| 101 | let evt_data: *const EvtPacket = self.ptr.cast(); | ||
| 102 | let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; | ||
| 103 | let evt_serial_buf: *const u8 = evt_serial.cast(); | ||
| 104 | |||
| 105 | let acl_data: *const AclDataPacket = self.ptr.cast(); | ||
| 106 | let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; | ||
| 107 | let acl_serial_buf: *const u8 = acl_serial.cast(); | ||
| 108 | |||
| 109 | if let TlPacketType::AclData = evt_kind { | ||
| 110 | let len = (*acl_serial).length as usize + 5; | ||
| 111 | if len > buf.len() { | ||
| 112 | return Err(()); | ||
| 113 | } | ||
| 114 | |||
| 115 | core::ptr::copy(evt_serial_buf, buf.as_mut_ptr(), len); | ||
| 116 | |||
| 117 | Ok(len) | ||
| 118 | } else { | ||
| 119 | let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE; | ||
| 120 | if len > buf.len() { | ||
| 121 | return Err(()); | ||
| 122 | } | ||
| 123 | |||
| 124 | core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len); | ||
| 125 | |||
| 126 | Ok(len) | ||
| 127 | } | ||
| 128 | } | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | impl Drop for EvtBox { | ||
| 133 | fn drop(&mut self) { | ||
| 134 | use crate::ipcc::Ipcc; | ||
| 135 | |||
| 136 | let mut ipcc = Ipcc::new_inner(unsafe { crate::Peripherals::steal() }.IPCC); | ||
| 137 | mm::MemoryManager::evt_drop(self.ptr, &mut ipcc); | ||
| 138 | } | ||
| 139 | } | ||
diff --git a/embassy-stm32/src/tl_mbox/mm.rs b/embassy-stm32/src/tl_mbox/mm.rs index cf4797305..f99ffa399 100644 --- a/embassy-stm32/src/tl_mbox/mm.rs +++ b/embassy-stm32/src/tl_mbox/mm.rs | |||
| @@ -1,18 +1,20 @@ | |||
| 1 | use core::mem::MaybeUninit; | 1 | use core::mem::MaybeUninit; |
| 2 | 2 | ||
| 3 | use super::unsafe_linked_list::LST_init_head; | 3 | use super::evt::EvtPacket; |
| 4 | use super::unsafe_linked_list::LinkedListNode; | ||
| 4 | use super::{ | 5 | use super::{ |
| 5 | MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUFF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF, | 6 | channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUFF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, |
| 6 | TL_MEM_MANAGER_TABLE, | 7 | SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, TL_REF_TABLE, |
| 7 | }; | 8 | }; |
| 9 | use crate::ipcc::Ipcc; | ||
| 8 | 10 | ||
| 9 | pub struct MemoryManager; | 11 | pub struct MemoryManager; |
| 10 | 12 | ||
| 11 | impl MemoryManager { | 13 | impl MemoryManager { |
| 12 | pub fn new() -> Self { | 14 | pub fn new() -> Self { |
| 13 | unsafe { | 15 | unsafe { |
| 14 | LST_init_head(FREE_BUFF_QUEUE.as_mut_ptr()); | 16 | LinkedListNode::init_head(FREE_BUFF_QUEUE.as_mut_ptr()); |
| 15 | LST_init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); | 17 | LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); |
| 16 | 18 | ||
| 17 | TL_MEM_MANAGER_TABLE = MaybeUninit::new(MemManagerTable { | 19 | TL_MEM_MANAGER_TABLE = MaybeUninit::new(MemManagerTable { |
| 18 | spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), | 20 | spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), |
| @@ -27,4 +29,43 @@ impl MemoryManager { | |||
| 27 | 29 | ||
| 28 | MemoryManager | 30 | MemoryManager |
| 29 | } | 31 | } |
| 32 | |||
| 33 | pub fn evt_handler(ipcc: &mut Ipcc) { | ||
| 34 | ipcc.c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false); | ||
| 35 | Self::send_free_buf(); | ||
| 36 | ipcc.c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); | ||
| 37 | } | ||
| 38 | |||
| 39 | pub fn evt_drop(evt: *mut EvtPacket, ipcc: &mut Ipcc) { | ||
| 40 | unsafe { | ||
| 41 | let list_node = evt.cast(); | ||
| 42 | |||
| 43 | LinkedListNode::remove_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); | ||
| 44 | } | ||
| 45 | |||
| 46 | let channel_is_busy = ipcc.c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); | ||
| 47 | |||
| 48 | // postpone event buffer freeing to IPCC interrupt handler | ||
| 49 | if channel_is_busy { | ||
| 50 | ipcc.c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); | ||
| 51 | } else { | ||
| 52 | Self::send_free_buf(); | ||
| 53 | ipcc.c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | fn send_free_buf() { | ||
| 58 | unsafe { | ||
| 59 | let mut node_ptr = core::ptr::null_mut(); | ||
| 60 | let node_ptr_ptr: *mut _ = &mut node_ptr; | ||
| 61 | |||
| 62 | while !LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { | ||
| 63 | LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), node_ptr_ptr); | ||
| 64 | LinkedListNode::insert_tail( | ||
| 65 | (*(*TL_REF_TABLE.as_ptr()).mem_manager_table).pevt_free_buffer_queue, | ||
| 66 | node_ptr, | ||
| 67 | ); | ||
| 68 | } | ||
| 69 | } | ||
| 70 | } | ||
| 30 | } | 71 | } |
diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32/src/tl_mbox/mod.rs index 73d2ca6d6..3651b8ea5 100644 --- a/embassy-stm32/src/tl_mbox/mod.rs +++ b/embassy-stm32/src/tl_mbox/mod.rs | |||
| @@ -1,20 +1,27 @@ | |||
| 1 | use core::mem::MaybeUninit; | 1 | use core::mem::MaybeUninit; |
| 2 | 2 | ||
| 3 | use bit_field::BitField; | 3 | use bit_field::BitField; |
| 4 | use embassy_cortex_m::interrupt::InterruptExt; | ||
| 5 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 6 | use embassy_sync::channel::Channel; | ||
| 4 | 7 | ||
| 5 | use self::ble::Ble; | 8 | use self::ble::Ble; |
| 6 | use self::cmd::{AclDataPacket, CmdPacket}; | 9 | use self::cmd::{AclDataPacket, CmdPacket}; |
| 7 | use self::evt::CsEvt; | 10 | use self::evt::{CsEvt, EvtBox}; |
| 8 | use self::mm::MemoryManager; | 11 | use self::mm::MemoryManager; |
| 12 | use self::shci::{shci_ble_init, ShciBleInitCmdParam}; | ||
| 9 | use self::sys::Sys; | 13 | use self::sys::Sys; |
| 10 | use self::unsafe_linked_list::LinkedListNode; | 14 | use self::unsafe_linked_list::LinkedListNode; |
| 15 | use crate::_generated::interrupt::{IPCC_C1_RX, IPCC_C1_TX}; | ||
| 11 | use crate::ipcc::Ipcc; | 16 | use crate::ipcc::Ipcc; |
| 12 | 17 | ||
| 13 | mod ble; | 18 | mod ble; |
| 14 | mod channels; | 19 | mod channels; |
| 15 | mod cmd; | 20 | mod cmd; |
| 21 | mod consts; | ||
| 16 | mod evt; | 22 | mod evt; |
| 17 | mod mm; | 23 | mod mm; |
| 24 | mod shci; | ||
| 18 | mod sys; | 25 | mod sys; |
| 19 | mod unsafe_linked_list; | 26 | mod unsafe_linked_list; |
| 20 | 27 | ||
| @@ -42,10 +49,10 @@ pub struct SafeBootInfoTable { | |||
| 42 | 49 | ||
| 43 | #[repr(C, packed)] | 50 | #[repr(C, packed)] |
| 44 | #[derive(Copy, Clone)] | 51 | #[derive(Copy, Clone)] |
| 45 | pub struct RssInfoTable { | 52 | pub struct FusInfoTable { |
| 46 | version: u32, | 53 | version: u32, |
| 47 | memory_size: u32, | 54 | memory_size: u32, |
| 48 | rss_info: u32, | 55 | fus_info: u32, |
| 49 | } | 56 | } |
| 50 | 57 | ||
| 51 | /// # Version | 58 | /// # Version |
| @@ -64,8 +71,8 @@ pub struct RssInfoTable { | |||
| 64 | pub struct WirelessFwInfoTable { | 71 | pub struct WirelessFwInfoTable { |
| 65 | version: u32, | 72 | version: u32, |
| 66 | memory_size: u32, | 73 | memory_size: u32, |
| 67 | thread_info: u32, | 74 | info_stack: u32, |
| 68 | ble_info: u32, | 75 | reserved: u32, |
| 69 | } | 76 | } |
| 70 | 77 | ||
| 71 | impl WirelessFwInfoTable { | 78 | impl WirelessFwInfoTable { |
| @@ -107,7 +114,7 @@ impl WirelessFwInfoTable { | |||
| 107 | #[derive(Copy, Clone)] | 114 | #[derive(Copy, Clone)] |
| 108 | pub struct DeviceInfoTable { | 115 | pub struct DeviceInfoTable { |
| 109 | pub safe_boot_info_table: SafeBootInfoTable, | 116 | pub safe_boot_info_table: SafeBootInfoTable, |
| 110 | pub rss_info_table: RssInfoTable, | 117 | pub fus_info_table: FusInfoTable, |
| 111 | pub wireless_fw_info_table: WirelessFwInfoTable, | 118 | pub wireless_fw_info_table: WirelessFwInfoTable, |
| 112 | } | 119 | } |
| 113 | 120 | ||
| @@ -191,6 +198,9 @@ pub struct RefTable { | |||
| 191 | mem_manager_table: *const MemManagerTable, | 198 | mem_manager_table: *const MemManagerTable, |
| 192 | traces_table: *const TracesTable, | 199 | traces_table: *const TracesTable, |
| 193 | mac_802_15_4_table: *const Mac802_15_4Table, | 200 | mac_802_15_4_table: *const Mac802_15_4Table, |
| 201 | zigbee_table: *const ZigbeeTable, | ||
| 202 | lld_tests_table: *const LldTestTable, | ||
| 203 | ble_lld_table: *const BleLldTable, | ||
| 194 | } | 204 | } |
| 195 | 205 | ||
| 196 | #[link_section = "TL_REF_TABLE"] | 206 | #[link_section = "TL_REF_TABLE"] |
| @@ -206,6 +216,12 @@ static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit(); | |||
| 206 | static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit(); | 216 | static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit(); |
| 207 | 217 | ||
| 208 | #[link_section = "MB_MEM1"] | 218 | #[link_section = "MB_MEM1"] |
| 219 | static mut TL_LLD_TESTS_TABLE: MaybeUninit<LldTestTable> = MaybeUninit::uninit(); | ||
| 220 | |||
| 221 | #[link_section = "MB_MEM1"] | ||
| 222 | static mut TL_BLE_LLD_TABLE: MaybeUninit<BleLldTable> = MaybeUninit::uninit(); | ||
| 223 | |||
| 224 | #[link_section = "MB_MEM1"] | ||
| 209 | static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit(); | 225 | static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit(); |
| 210 | 226 | ||
| 211 | #[link_section = "MB_MEM1"] | 227 | #[link_section = "MB_MEM1"] |
| @@ -217,17 +233,16 @@ static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit(); | |||
| 217 | #[link_section = "MB_MEM1"] | 233 | #[link_section = "MB_MEM1"] |
| 218 | static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit(); | 234 | static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit(); |
| 219 | 235 | ||
| 236 | #[link_section = "MB_MEM1"] | ||
| 237 | static mut TL_ZIGBEE_TABLE: MaybeUninit<ZigbeeTable> = MaybeUninit::uninit(); | ||
| 238 | |||
| 220 | #[allow(dead_code)] // Not used currently but reserved | 239 | #[allow(dead_code)] // Not used currently but reserved |
| 221 | #[link_section = "MB_MEM2"] | 240 | #[link_section = "MB_MEM1"] |
| 222 | static mut FREE_BUFF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | 241 | static mut FREE_BUFF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); |
| 223 | 242 | ||
| 224 | // not in shared RAM | 243 | // not in shared RAM |
| 225 | static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | 244 | static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); |
| 226 | 245 | ||
| 227 | #[allow(dead_code)] // Not used currently but reserved | ||
| 228 | #[link_section = "MB_MEM2"] | ||
| 229 | static mut TRACES_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 230 | |||
| 231 | #[link_section = "MB_MEM2"] | 246 | #[link_section = "MB_MEM2"] |
| 232 | static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> = | 247 | static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> = |
| 233 | MaybeUninit::uninit(); | 248 | MaybeUninit::uninit(); |
| @@ -259,6 +274,9 @@ static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); | |||
| 259 | // "magic" numbers from ST ---v---v | 274 | // "magic" numbers from ST ---v---v |
| 260 | static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); | 275 | static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); |
| 261 | 276 | ||
| 277 | // TODO: get a better size, this is a placeholder | ||
| 278 | pub(crate) static TL_CHANNEL: Channel<CriticalSectionRawMutex, EvtBox, 5> = Channel::new(); | ||
| 279 | |||
| 262 | pub struct TlMbox { | 280 | pub struct TlMbox { |
| 263 | _sys: Sys, | 281 | _sys: Sys, |
| 264 | _ble: Ble, | 282 | _ble: Ble, |
| @@ -267,7 +285,7 @@ pub struct TlMbox { | |||
| 267 | 285 | ||
| 268 | impl TlMbox { | 286 | impl TlMbox { |
| 269 | /// initializes low-level transport between CPU1 and BLE stack on CPU2 | 287 | /// initializes low-level transport between CPU1 and BLE stack on CPU2 |
| 270 | pub fn init(ipcc: &mut Ipcc) -> TlMbox { | 288 | pub fn init(ipcc: &mut Ipcc, rx_irq: IPCC_C1_RX, tx_irq: IPCC_C1_TX) -> TlMbox { |
| 271 | unsafe { | 289 | unsafe { |
| 272 | TL_REF_TABLE = MaybeUninit::new(RefTable { | 290 | TL_REF_TABLE = MaybeUninit::new(RefTable { |
| 273 | device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(), | 291 | device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(), |
| @@ -277,6 +295,9 @@ impl TlMbox { | |||
| 277 | mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), | 295 | mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), |
| 278 | traces_table: TL_TRACES_TABLE.as_ptr(), | 296 | traces_table: TL_TRACES_TABLE.as_ptr(), |
| 279 | mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), | 297 | mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), |
| 298 | zigbee_table: TL_ZIGBEE_TABLE.as_ptr(), | ||
| 299 | lld_tests_table: TL_LLD_TESTS_TABLE.as_ptr(), | ||
| 300 | ble_lld_table: TL_BLE_LLD_TABLE.as_ptr(), | ||
| 280 | }); | 301 | }); |
| 281 | 302 | ||
| 282 | TL_SYS_TABLE = MaybeUninit::zeroed(); | 303 | TL_SYS_TABLE = MaybeUninit::zeroed(); |
| @@ -286,6 +307,9 @@ impl TlMbox { | |||
| 286 | TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed(); | 307 | TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed(); |
| 287 | TL_TRACES_TABLE = MaybeUninit::zeroed(); | 308 | TL_TRACES_TABLE = MaybeUninit::zeroed(); |
| 288 | TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed(); | 309 | TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed(); |
| 310 | TL_ZIGBEE_TABLE = MaybeUninit::zeroed(); | ||
| 311 | TL_LLD_TESTS_TABLE = MaybeUninit::zeroed(); | ||
| 312 | TL_BLE_LLD_TABLE = MaybeUninit::zeroed(); | ||
| 289 | 313 | ||
| 290 | EVT_POOL = MaybeUninit::zeroed(); | 314 | EVT_POOL = MaybeUninit::zeroed(); |
| 291 | SYS_SPARE_EVT_BUF = MaybeUninit::zeroed(); | 315 | SYS_SPARE_EVT_BUF = MaybeUninit::zeroed(); |
| @@ -302,6 +326,24 @@ impl TlMbox { | |||
| 302 | let _ble = Ble::new(ipcc); | 326 | let _ble = Ble::new(ipcc); |
| 303 | let _mm = MemoryManager::new(); | 327 | let _mm = MemoryManager::new(); |
| 304 | 328 | ||
| 329 | rx_irq.disable(); | ||
| 330 | tx_irq.disable(); | ||
| 331 | |||
| 332 | rx_irq.set_handler_context(ipcc.as_mut_ptr() as *mut ()); | ||
| 333 | tx_irq.set_handler_context(ipcc.as_mut_ptr() as *mut ()); | ||
| 334 | |||
| 335 | rx_irq.set_handler(|ipcc| { | ||
| 336 | let ipcc: &mut Ipcc = unsafe { &mut *ipcc.cast() }; | ||
| 337 | Self::interrupt_ipcc_rx_handler(ipcc); | ||
| 338 | }); | ||
| 339 | tx_irq.set_handler(|ipcc| { | ||
| 340 | let ipcc: &mut Ipcc = unsafe { &mut *ipcc.cast() }; | ||
| 341 | Self::interrupt_ipcc_tx_handler(ipcc); | ||
| 342 | }); | ||
| 343 | |||
| 344 | rx_irq.enable(); | ||
| 345 | tx_irq.enable(); | ||
| 346 | |||
| 305 | TlMbox { _sys, _ble, _mm } | 347 | TlMbox { _sys, _ble, _mm } |
| 306 | } | 348 | } |
| 307 | 349 | ||
| @@ -315,4 +357,41 @@ impl TlMbox { | |||
| 315 | None | 357 | None |
| 316 | } | 358 | } |
| 317 | } | 359 | } |
| 360 | |||
| 361 | pub fn shci_ble_init(&self, ipcc: &mut Ipcc, param: ShciBleInitCmdParam) { | ||
| 362 | shci_ble_init(ipcc, param); | ||
| 363 | } | ||
| 364 | |||
| 365 | pub fn send_ble_cmd(&self, ipcc: &mut Ipcc, buf: &[u8]) { | ||
| 366 | ble::Ble::send_cmd(ipcc, buf); | ||
| 367 | } | ||
| 368 | |||
| 369 | // pub fn send_sys_cmd(&self, ipcc: &mut Ipcc, buf: &[u8]) { | ||
| 370 | // sys::Sys::send_cmd(ipcc, buf); | ||
| 371 | // } | ||
| 372 | |||
| 373 | pub async fn read(&self) -> EvtBox { | ||
| 374 | TL_CHANNEL.recv().await | ||
| 375 | } | ||
| 376 | |||
| 377 | fn interrupt_ipcc_rx_handler(ipcc: &mut Ipcc) { | ||
| 378 | if ipcc.is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { | ||
| 379 | sys::Sys::evt_handler(ipcc); | ||
| 380 | } else if ipcc.is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) { | ||
| 381 | ble::Ble::evt_handler(ipcc); | ||
| 382 | } else { | ||
| 383 | todo!() | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 | fn interrupt_ipcc_tx_handler(ipcc: &mut Ipcc) { | ||
| 388 | if ipcc.is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { | ||
| 389 | // TODO: handle this case | ||
| 390 | let _ = sys::Sys::cmd_evt_handler(ipcc); | ||
| 391 | } else if ipcc.is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) { | ||
| 392 | mm::MemoryManager::evt_handler(ipcc); | ||
| 393 | } else { | ||
| 394 | todo!() | ||
| 395 | } | ||
| 396 | } | ||
| 318 | } | 397 | } |
diff --git a/embassy-stm32/src/tl_mbox/shci.rs b/embassy-stm32/src/tl_mbox/shci.rs new file mode 100644 index 000000000..61fd9e4a3 --- /dev/null +++ b/embassy-stm32/src/tl_mbox/shci.rs | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | //! HCI commands for system channel | ||
| 2 | |||
| 3 | use super::cmd::CmdPacket; | ||
| 4 | use super::consts::TlPacketType; | ||
| 5 | use super::{channels, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE}; | ||
| 6 | use crate::ipcc::Ipcc; | ||
| 7 | |||
| 8 | const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66; | ||
| 9 | pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE; | ||
| 10 | #[allow(dead_code)] | ||
| 11 | const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; | ||
| 12 | |||
| 13 | #[derive(Clone, Copy)] | ||
| 14 | #[repr(C, packed)] | ||
| 15 | pub struct ShciBleInitCmdParam { | ||
| 16 | /// NOT USED CURRENTLY | ||
| 17 | pub p_ble_buffer_address: u32, | ||
| 18 | |||
| 19 | /// Size of the Buffer allocated in pBleBufferAddress | ||
| 20 | pub ble_buffer_size: u32, | ||
| 21 | |||
| 22 | pub num_attr_record: u16, | ||
| 23 | pub num_attr_serv: u16, | ||
| 24 | pub attr_value_arr_size: u16, | ||
| 25 | pub num_of_links: u8, | ||
| 26 | pub extended_packet_length_enable: u8, | ||
| 27 | pub pr_write_list_size: u8, | ||
| 28 | pub mb_lock_count: u8, | ||
| 29 | |||
| 30 | pub att_mtu: u16, | ||
| 31 | pub slave_sca: u16, | ||
| 32 | pub master_sca: u8, | ||
| 33 | pub ls_source: u8, | ||
| 34 | pub max_conn_event_length: u32, | ||
| 35 | pub hs_startup_time: u16, | ||
| 36 | pub viterbi_enable: u8, | ||
| 37 | pub ll_only: u8, | ||
| 38 | pub hw_version: u8, | ||
| 39 | } | ||
| 40 | |||
| 41 | impl Default for ShciBleInitCmdParam { | ||
| 42 | fn default() -> Self { | ||
| 43 | Self { | ||
| 44 | p_ble_buffer_address: 0, | ||
| 45 | ble_buffer_size: 0, | ||
| 46 | num_attr_record: 68, | ||
| 47 | num_attr_serv: 8, | ||
| 48 | attr_value_arr_size: 1344, | ||
| 49 | num_of_links: 2, | ||
| 50 | extended_packet_length_enable: 1, | ||
| 51 | pr_write_list_size: 0x3A, | ||
| 52 | mb_lock_count: 0x79, | ||
| 53 | att_mtu: 156, | ||
| 54 | slave_sca: 500, | ||
| 55 | master_sca: 0, | ||
| 56 | ls_source: 1, | ||
| 57 | max_conn_event_length: 0xFFFFFFFF, | ||
| 58 | hs_startup_time: 0x148, | ||
| 59 | viterbi_enable: 1, | ||
| 60 | ll_only: 0, | ||
| 61 | hw_version: 0, | ||
| 62 | } | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | #[derive(Clone, Copy, Default)] | ||
| 67 | #[repr(C, packed)] | ||
| 68 | pub struct ShciHeader { | ||
| 69 | metadata: [u32; 3], | ||
| 70 | } | ||
| 71 | |||
| 72 | #[derive(Clone, Copy)] | ||
| 73 | #[repr(C, packed)] | ||
| 74 | pub struct ShciBleInitCmdPacket { | ||
| 75 | header: ShciHeader, | ||
| 76 | param: ShciBleInitCmdParam, | ||
| 77 | } | ||
| 78 | |||
| 79 | pub fn shci_ble_init(ipcc: &mut Ipcc, param: ShciBleInitCmdParam) { | ||
| 80 | let mut packet = ShciBleInitCmdPacket { | ||
| 81 | header: ShciHeader::default(), | ||
| 82 | param, | ||
| 83 | }; | ||
| 84 | |||
| 85 | let packet_ptr: *mut ShciBleInitCmdPacket = &mut packet; | ||
| 86 | |||
| 87 | unsafe { | ||
| 88 | let cmd_ptr: *mut CmdPacket = packet_ptr.cast(); | ||
| 89 | |||
| 90 | (*cmd_ptr).cmd_serial.cmd.cmd_code = SCHI_OPCODE_BLE_INIT; | ||
| 91 | (*cmd_ptr).cmd_serial.cmd.payload_len = core::mem::size_of::<ShciBleInitCmdParam>() as u8; | ||
| 92 | |||
| 93 | let cmd_buf = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; | ||
| 94 | core::ptr::write(cmd_buf, *cmd_ptr); | ||
| 95 | |||
| 96 | cmd_buf.cmd_serial.ty = TlPacketType::SysCmd as u8; | ||
| 97 | |||
| 98 | ipcc.c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); | ||
| 99 | ipcc.c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); | ||
| 100 | } | ||
| 101 | } | ||
diff --git a/embassy-stm32/src/tl_mbox/sys.rs b/embassy-stm32/src/tl_mbox/sys.rs index 13ae7f9f9..31ebde721 100644 --- a/embassy-stm32/src/tl_mbox/sys.rs +++ b/embassy-stm32/src/tl_mbox/sys.rs | |||
| @@ -1,15 +1,20 @@ | |||
| 1 | use core::mem::MaybeUninit; | 1 | use core::mem::MaybeUninit; |
| 2 | 2 | ||
| 3 | use super::unsafe_linked_list::LST_init_head; | 3 | use embassy_futures::block_on; |
| 4 | use super::{channels, SysTable, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; | 4 | |
| 5 | use super::cmd::{CmdPacket, CmdSerial}; | ||
| 6 | use super::consts::TlPacketType; | ||
| 7 | use super::evt::{CcEvt, EvtBox, EvtSerial}; | ||
| 8 | use super::unsafe_linked_list::LinkedListNode; | ||
| 9 | use super::{channels, SysTable, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_CHANNEL, TL_REF_TABLE, TL_SYS_TABLE}; | ||
| 5 | use crate::ipcc::Ipcc; | 10 | use crate::ipcc::Ipcc; |
| 6 | 11 | ||
| 7 | pub struct Sys; | 12 | pub struct Sys; |
| 8 | 13 | ||
| 9 | impl Sys { | 14 | impl Sys { |
| 10 | pub fn new(ipcc: &mut Ipcc) -> Self { | 15 | pub(crate) fn new(ipcc: &mut Ipcc) -> Self { |
| 11 | unsafe { | 16 | unsafe { |
| 12 | LST_init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); | 17 | LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); |
| 13 | 18 | ||
| 14 | TL_SYS_TABLE = MaybeUninit::new(SysTable { | 19 | TL_SYS_TABLE = MaybeUninit::new(SysTable { |
| 15 | pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), | 20 | pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), |
| @@ -21,4 +26,62 @@ impl Sys { | |||
| 21 | 26 | ||
| 22 | Sys | 27 | Sys |
| 23 | } | 28 | } |
| 29 | |||
| 30 | pub(crate) fn evt_handler(ipcc: &mut Ipcc) { | ||
| 31 | unsafe { | ||
| 32 | let mut node_ptr = core::ptr::null_mut(); | ||
| 33 | let node_ptr_ptr: *mut _ = &mut node_ptr; | ||
| 34 | |||
| 35 | while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { | ||
| 36 | LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); | ||
| 37 | |||
| 38 | let event = node_ptr.cast(); | ||
| 39 | let event = EvtBox::new(event); | ||
| 40 | |||
| 41 | // TODO: not really happy about this | ||
| 42 | block_on(TL_CHANNEL.send(event)); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | ipcc.c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); | ||
| 47 | } | ||
| 48 | |||
| 49 | pub(crate) fn cmd_evt_handler(ipcc: &mut Ipcc) -> CcEvt { | ||
| 50 | ipcc.c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, false); | ||
| 51 | |||
| 52 | // ST's command response data structure is really convoluted. | ||
| 53 | // | ||
| 54 | // for command response events on SYS channel, the header is missing | ||
| 55 | // and one should: | ||
| 56 | // 1. interpret the content of CMD_BUFFER as CmdPacket | ||
| 57 | // 2. Access CmdPacket's cmdserial field and interpret its content as EvtSerial | ||
| 58 | // 3. Access EvtSerial's evt field (as Evt) and interpret its payload as CcEvt | ||
| 59 | // 4. CcEvt type is the actual SHCI response | ||
| 60 | // 5. profit | ||
| 61 | unsafe { | ||
| 62 | let cmd: *const CmdPacket = (*TL_SYS_TABLE.as_ptr()).pcmd_buffer; | ||
| 63 | let cmd_serial: *const CmdSerial = &(*cmd).cmd_serial; | ||
| 64 | let evt_serial: *const EvtSerial = cmd_serial.cast(); | ||
| 65 | let cc = (*evt_serial).evt.payload.as_ptr().cast(); | ||
| 66 | *cc | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | #[allow(dead_code)] | ||
| 71 | pub(crate) fn send_cmd(ipcc: &mut Ipcc, buf: &[u8]) { | ||
| 72 | unsafe { | ||
| 73 | // TODO: check this | ||
| 74 | let cmd_buffer = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer; | ||
| 75 | let cmd_serial: *mut CmdSerial = &mut (*cmd_buffer).cmd_serial; | ||
| 76 | let cmd_serial_buf = cmd_serial.cast(); | ||
| 77 | |||
| 78 | core::ptr::copy(buf.as_ptr(), cmd_serial_buf, buf.len()); | ||
| 79 | |||
| 80 | let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer; | ||
| 81 | cmd_packet.cmd_serial.ty = TlPacketType::SysCmd as u8; | ||
| 82 | |||
| 83 | ipcc.c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); | ||
| 84 | ipcc.c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); | ||
| 85 | } | ||
| 86 | } | ||
| 24 | } | 87 | } |
diff --git a/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs b/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs index 9caf01d1d..482e2bf5a 100644 --- a/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs +++ b/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs | |||
| @@ -29,95 +29,97 @@ impl Default for LinkedListNode { | |||
| 29 | } | 29 | } |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | pub unsafe fn LST_init_head(mut listHead: *mut LinkedListNode) { | 32 | impl LinkedListNode { |
| 33 | (*listHead).next = listHead; | 33 | pub unsafe fn init_head(mut list_head: *mut LinkedListNode) { |
| 34 | (*listHead).prev = listHead; | 34 | (*list_head).next = list_head; |
| 35 | } | 35 | (*list_head).prev = list_head; |
| 36 | } | ||
| 36 | 37 | ||
| 37 | pub unsafe fn LST_is_empty(mut listHead: *mut LinkedListNode) -> bool { | 38 | pub unsafe fn is_empty(mut list_head: *mut LinkedListNode) -> bool { |
| 38 | interrupt::free(|_| ((*listHead).next) == listHead) | 39 | interrupt::free(|_| ((*list_head).next) == list_head) |
| 39 | } | 40 | } |
| 40 | 41 | ||
| 41 | pub unsafe fn LST_insert_head(mut listHead: *mut LinkedListNode, mut node: *mut LinkedListNode) { | 42 | pub unsafe fn insert_head(mut list_head: *mut LinkedListNode, mut node: *mut LinkedListNode) { |
| 42 | interrupt::free(|_| { | 43 | interrupt::free(|_| { |
| 43 | (*node).next = (*listHead).next; | 44 | (*node).next = (*list_head).next; |
| 44 | (*node).prev = listHead; | 45 | (*node).prev = list_head; |
| 45 | (*listHead).next = node; | 46 | (*list_head).next = node; |
| 46 | (*(*node).next).prev = node; | 47 | (*(*node).next).prev = node; |
| 47 | }); | 48 | }); |
| 48 | } | 49 | } |
| 49 | 50 | ||
| 50 | pub unsafe fn LST_insert_tail(mut listHead: *mut LinkedListNode, mut node: *mut LinkedListNode) { | 51 | pub unsafe fn insert_tail(mut list_head: *mut LinkedListNode, mut node: *mut LinkedListNode) { |
| 51 | interrupt::free(|_| { | 52 | interrupt::free(|_| { |
| 52 | (*node).next = listHead; | 53 | (*node).next = list_head; |
| 53 | (*node).prev = (*listHead).prev; | 54 | (*node).prev = (*list_head).prev; |
| 54 | (*listHead).prev = node; | 55 | (*list_head).prev = node; |
| 55 | (*(*node).prev).next = node; | 56 | (*(*node).prev).next = node; |
| 56 | }); | 57 | }); |
| 57 | } | 58 | } |
| 58 | 59 | ||
| 59 | pub unsafe fn LST_remove_node(mut node: *mut LinkedListNode) { | 60 | pub unsafe fn remove_node(mut node: *mut LinkedListNode) { |
| 60 | interrupt::free(|_| { | 61 | interrupt::free(|_| { |
| 61 | (*(*node).prev).next = (*node).next; | 62 | (*(*node).prev).next = (*node).next; |
| 62 | (*(*node).next).prev = (*node).prev; | 63 | (*(*node).next).prev = (*node).prev; |
| 63 | }); | 64 | }); |
| 64 | } | 65 | } |
| 65 | 66 | ||
| 66 | pub unsafe fn LST_remove_head(mut listHead: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { | 67 | pub unsafe fn remove_head(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { |
| 67 | interrupt::free(|_| { | 68 | interrupt::free(|_| { |
| 68 | *node = (*listHead).next; | 69 | *node = (*list_head).next; |
| 69 | LST_remove_node((*listHead).next); | 70 | Self::remove_node((*list_head).next); |
| 70 | }); | 71 | }); |
| 71 | } | 72 | } |
| 72 | 73 | ||
| 73 | pub unsafe fn LST_remove_tail(mut listHead: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { | 74 | pub unsafe fn remove_tail(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { |
| 74 | interrupt::free(|_| { | 75 | interrupt::free(|_| { |
| 75 | *node = (*listHead).prev; | 76 | *node = (*list_head).prev; |
| 76 | LST_remove_node((*listHead).prev); | 77 | Self::remove_node((*list_head).prev); |
| 77 | }); | 78 | }); |
| 78 | } | 79 | } |
| 79 | 80 | ||
| 80 | pub unsafe fn LST_insert_node_after(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) { | 81 | pub unsafe fn insert_node_after(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) { |
| 81 | interrupt::free(|_| { | 82 | interrupt::free(|_| { |
| 82 | (*node).next = (*ref_node).next; | 83 | (*node).next = (*ref_node).next; |
| 83 | (*node).prev = ref_node; | 84 | (*node).prev = ref_node; |
| 84 | (*ref_node).next = node; | 85 | (*ref_node).next = node; |
| 85 | (*(*node).next).prev = node; | 86 | (*(*node).next).prev = node; |
| 86 | }); | 87 | }); |
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | pub unsafe fn LST_insert_node_before(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) { | 90 | pub unsafe fn insert_node_before(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) { |
| 90 | interrupt::free(|_| { | 91 | interrupt::free(|_| { |
| 91 | (*node).next = ref_node; | 92 | (*node).next = ref_node; |
| 92 | (*node).prev = (*ref_node).prev; | 93 | (*node).prev = (*ref_node).prev; |
| 93 | (*ref_node).prev = node; | 94 | (*ref_node).prev = node; |
| 94 | (*(*node).prev).next = node; | 95 | (*(*node).prev).next = node; |
| 95 | }); | 96 | }); |
| 96 | } | 97 | } |
| 97 | 98 | ||
| 98 | pub unsafe fn LST_get_size(mut listHead: *mut LinkedListNode) -> usize { | 99 | pub unsafe fn get_size(mut list_head: *mut LinkedListNode) -> usize { |
| 99 | interrupt::free(|_| { | 100 | interrupt::free(|_| { |
| 100 | let mut size = 0; | 101 | let mut size = 0; |
| 101 | let mut temp: *mut LinkedListNode = core::ptr::null_mut::<LinkedListNode>(); | 102 | let mut temp: *mut LinkedListNode = core::ptr::null_mut::<LinkedListNode>(); |
| 102 | 103 | ||
| 103 | temp = (*listHead).next; | 104 | temp = (*list_head).next; |
| 104 | while temp != listHead { | 105 | while temp != list_head { |
| 105 | size += 1; | 106 | size += 1; |
| 106 | temp = (*temp).next | 107 | temp = (*temp).next |
| 107 | } | 108 | } |
| 108 | 109 | ||
| 109 | size | 110 | size |
| 110 | }) | 111 | }) |
| 111 | } | 112 | } |
| 112 | 113 | ||
| 113 | pub unsafe fn LST_get_next_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { | 114 | pub unsafe fn get_next_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { |
| 114 | interrupt::free(|_| { | 115 | interrupt::free(|_| { |
| 115 | *node = (*ref_node).next; | 116 | *node = (*ref_node).next; |
| 116 | }); | 117 | }); |
| 117 | } | 118 | } |
| 118 | 119 | ||
| 119 | pub unsafe fn LST_get_prev_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { | 120 | pub unsafe fn get_prev_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { |
| 120 | interrupt::free(|_| { | 121 | interrupt::free(|_| { |
| 121 | *node = (*ref_node).prev; | 122 | *node = (*ref_node).prev; |
| 122 | }); | 123 | }); |
| 124 | } | ||
| 123 | } | 125 | } |
