diff options
| -rw-r--r-- | embassy-stm32/src/tl_mbox/ble.rs | 39 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/cmd.rs | 42 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/consts.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/evt.rs | 106 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/hci.rs | 60 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/mm.rs | 58 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/mod.rs | 359 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/shci.rs | 35 | ||||
| -rw-r--r-- | embassy-stm32/src/tl_mbox/sys.rs | 67 | ||||
| -rw-r--r-- | examples/stm32wb/src/bin/tl_mbox_tx_rx.rs | 55 |
10 files changed, 482 insertions, 343 deletions
diff --git a/embassy-stm32/src/tl_mbox/ble.rs b/embassy-stm32/src/tl_mbox/ble.rs index 062377999..45bf81ef2 100644 --- a/embassy-stm32/src/tl_mbox/ble.rs +++ b/embassy-stm32/src/tl_mbox/ble.rs | |||
| @@ -1,35 +1,36 @@ | |||
| 1 | use embassy_futures::block_on; | 1 | use embassy_futures::block_on; |
| 2 | 2 | ||
| 3 | use super::cmd::CmdSerial; | 3 | use super::cmd::{CmdPacket, CmdSerial}; |
| 4 | use super::consts::TlPacketType; | 4 | use super::consts::TlPacketType; |
| 5 | use super::evt::EvtBox; | 5 | use super::evt::EvtBox; |
| 6 | use super::ipcc::Ipcc; | ||
| 6 | use super::unsafe_linked_list::LinkedListNode; | 7 | use super::unsafe_linked_list::LinkedListNode; |
| 7 | use super::{ | 8 | use super::{ |
| 8 | channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE, TL_CHANNEL, | 9 | channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, HEAPLESS_EVT_QUEUE, TL_BLE_TABLE, |
| 9 | TL_REF_TABLE, | 10 | TL_REF_TABLE, |
| 10 | }; | 11 | }; |
| 11 | use crate::tl_mbox::cmd::CmdPacket; | ||
| 12 | use crate::tl_mbox::ipcc::Ipcc; | ||
| 13 | 12 | ||
| 14 | pub struct Ble; | 13 | pub struct Ble; |
| 15 | 14 | ||
| 16 | impl Ble { | 15 | impl Ble { |
| 17 | pub fn enable() { | 16 | pub(super) fn new() -> Self { |
| 18 | unsafe { | 17 | unsafe { |
| 19 | LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); | 18 | LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); |
| 20 | 19 | ||
| 21 | TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable { | 20 | TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable { |
| 22 | pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), | 21 | pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), |
| 23 | pcs_buffer: CS_BUFFER.as_mut_ptr().cast(), | 22 | pcs_buffer: CS_BUFFER.as_ptr().cast(), |
| 24 | pevt_queue: EVT_QUEUE.as_ptr().cast(), | 23 | pevt_queue: EVT_QUEUE.as_ptr().cast(), |
| 25 | phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(), | 24 | phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(), |
| 26 | }); | 25 | }); |
| 27 | } | 26 | } |
| 28 | 27 | ||
| 29 | Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true); | 28 | Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true); |
| 29 | |||
| 30 | Ble | ||
| 30 | } | 31 | } |
| 31 | 32 | ||
| 32 | pub fn evt_handler() { | 33 | pub(super) fn evt_handler() { |
| 33 | unsafe { | 34 | unsafe { |
| 34 | let mut node_ptr = core::ptr::null_mut(); | 35 | let mut node_ptr = core::ptr::null_mut(); |
| 35 | let node_ptr_ptr: *mut _ = &mut node_ptr; | 36 | let node_ptr_ptr: *mut _ = &mut node_ptr; |
| @@ -40,25 +41,41 @@ impl Ble { | |||
| 40 | let event = node_ptr.cast(); | 41 | let event = node_ptr.cast(); |
| 41 | let event = EvtBox::new(event); | 42 | let event = EvtBox::new(event); |
| 42 | 43 | ||
| 43 | block_on(TL_CHANNEL.send(event)); | 44 | block_on(HEAPLESS_EVT_QUEUE.send(event)); |
| 44 | } | 45 | } |
| 45 | } | 46 | } |
| 46 | 47 | ||
| 47 | Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL); | 48 | Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL); |
| 48 | } | 49 | } |
| 49 | 50 | ||
| 51 | pub(super) fn acl_data_handler(&self) { | ||
| 52 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, false); | ||
| 53 | |||
| 54 | // TODO: ACL data ack to the user | ||
| 55 | } | ||
| 56 | |||
| 50 | pub fn send_cmd(buf: &[u8]) { | 57 | pub fn send_cmd(buf: &[u8]) { |
| 51 | unsafe { | 58 | unsafe { |
| 52 | let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; | 59 | let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; |
| 53 | let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmd_serial; | 60 | let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmdserial; |
| 54 | let pcmd_serial_buf: *mut u8 = pcmd_serial.cast(); | 61 | let pcmd_serial_buf: *mut u8 = pcmd_serial.cast(); |
| 55 | 62 | ||
| 56 | core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len()); | 63 | core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len()); |
| 57 | 64 | ||
| 58 | let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; | 65 | let mut cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; |
| 59 | cmd_packet.cmd_serial.ty = TlPacketType::BleCmd as u8; | 66 | cmd_packet.cmdserial.ty = TlPacketType::BleCmd as u8; |
| 60 | } | 67 | } |
| 61 | 68 | ||
| 62 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL); | 69 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL); |
| 63 | } | 70 | } |
| 71 | |||
| 72 | #[allow(dead_code)] // Not used currently but reserved | ||
| 73 | pub(super) fn send_acl_data() { | ||
| 74 | let cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; | ||
| 75 | |||
| 76 | cmd_packet.acl_data_serial.ty = TlPacketType::AclData as u8; | ||
| 77 | |||
| 78 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL); | ||
| 79 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, true); | ||
| 80 | } | ||
| 64 | } | 81 | } |
diff --git a/embassy-stm32/src/tl_mbox/cmd.rs b/embassy-stm32/src/tl_mbox/cmd.rs index 3507c3231..781aa669d 100644 --- a/embassy-stm32/src/tl_mbox/cmd.rs +++ b/embassy-stm32/src/tl_mbox/cmd.rs | |||
| @@ -1,7 +1,8 @@ | |||
| 1 | use super::PacketHeader; | 1 | use crate::tl_mbox::evt::{EvtPacket, EvtSerial}; |
| 2 | use crate::tl_mbox::{PacketHeader, TL_EVT_HEADER_SIZE}; | ||
| 2 | 3 | ||
| 3 | #[repr(C, packed)] | ||
| 4 | #[derive(Copy, Clone)] | 4 | #[derive(Copy, Clone)] |
| 5 | #[repr(C, packed)] | ||
| 5 | pub struct Cmd { | 6 | pub struct Cmd { |
| 6 | pub cmd_code: u16, | 7 | pub cmd_code: u16, |
| 7 | pub payload_len: u8, | 8 | pub payload_len: u8, |
| @@ -18,22 +19,49 @@ impl Default for Cmd { | |||
| 18 | } | 19 | } |
| 19 | } | 20 | } |
| 20 | 21 | ||
| 21 | #[repr(C, packed)] | ||
| 22 | #[derive(Copy, Clone, Default)] | 22 | #[derive(Copy, Clone, Default)] |
| 23 | #[repr(C, packed)] | ||
| 23 | pub struct CmdSerial { | 24 | pub struct CmdSerial { |
| 24 | pub ty: u8, | 25 | pub ty: u8, |
| 25 | pub cmd: Cmd, | 26 | pub cmd: Cmd, |
| 26 | } | 27 | } |
| 27 | 28 | ||
| 28 | #[repr(C, packed)] | ||
| 29 | #[derive(Copy, Clone, Default)] | 29 | #[derive(Copy, Clone, Default)] |
| 30 | #[repr(C, packed)] | ||
| 30 | pub struct CmdPacket { | 31 | pub struct CmdPacket { |
| 31 | pub header: PacketHeader, | 32 | pub header: PacketHeader, |
| 32 | pub cmd_serial: CmdSerial, | 33 | pub cmdserial: CmdSerial, |
| 34 | } | ||
| 35 | |||
| 36 | impl CmdPacket { | ||
| 37 | /// Writes an underlying CmdPacket into the provided buffer. | ||
| 38 | /// Returns a number of bytes that were written. | ||
| 39 | /// Returns an error if event kind is unknown or if provided buffer size is not enough. | ||
| 40 | #[allow(clippy::result_unit_err)] | ||
| 41 | pub fn write(&self, buf: &mut [u8]) -> Result<usize, ()> { | ||
| 42 | unsafe { | ||
| 43 | let cmd_ptr: *const CmdPacket = self; | ||
| 44 | let self_as_evt_ptr: *const EvtPacket = cmd_ptr.cast(); | ||
| 45 | let evt_serial: *const EvtSerial = &(*self_as_evt_ptr).evt_serial; | ||
| 46 | |||
| 47 | let acl_data: *const AclDataPacket = cmd_ptr.cast(); | ||
| 48 | let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; | ||
| 49 | let acl_serial_buf: *const u8 = acl_serial.cast(); | ||
| 50 | |||
| 51 | let len = (*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE; | ||
| 52 | if len > buf.len() { | ||
| 53 | return Err(()); | ||
| 54 | } | ||
| 55 | |||
| 56 | core::ptr::copy(acl_serial_buf, buf.as_mut_ptr(), len); | ||
| 57 | |||
| 58 | Ok(len) | ||
| 59 | } | ||
| 60 | } | ||
| 33 | } | 61 | } |
| 34 | 62 | ||
| 35 | #[repr(C, packed)] | ||
| 36 | #[derive(Copy, Clone)] | 63 | #[derive(Copy, Clone)] |
| 64 | #[repr(C, packed)] | ||
| 37 | pub struct AclDataSerial { | 65 | pub struct AclDataSerial { |
| 38 | pub ty: u8, | 66 | pub ty: u8, |
| 39 | pub handle: u16, | 67 | pub handle: u16, |
| @@ -41,8 +69,8 @@ pub struct AclDataSerial { | |||
| 41 | pub acl_data: [u8; 1], | 69 | pub acl_data: [u8; 1], |
| 42 | } | 70 | } |
| 43 | 71 | ||
| 44 | #[repr(C, packed)] | ||
| 45 | #[derive(Copy, Clone)] | 72 | #[derive(Copy, Clone)] |
| 73 | #[repr(C, packed)] | ||
| 46 | pub struct AclDataPacket { | 74 | pub struct AclDataPacket { |
| 47 | pub header: PacketHeader, | 75 | pub header: PacketHeader, |
| 48 | pub acl_data_serial: AclDataSerial, | 76 | pub acl_data_serial: AclDataSerial, |
diff --git a/embassy-stm32/src/tl_mbox/consts.rs b/embassy-stm32/src/tl_mbox/consts.rs index e16a26cd0..caf26c06b 100644 --- a/embassy-stm32/src/tl_mbox/consts.rs +++ b/embassy-stm32/src/tl_mbox/consts.rs | |||
| @@ -1,4 +1,6 @@ | |||
| 1 | #[derive(PartialEq)] | 1 | use core::convert::TryFrom; |
| 2 | |||
| 3 | #[derive(Debug)] | ||
| 2 | #[repr(C)] | 4 | #[repr(C)] |
| 3 | pub enum TlPacketType { | 5 | pub enum TlPacketType { |
| 4 | BleCmd = 0x01, | 6 | BleCmd = 0x01, |
diff --git a/embassy-stm32/src/tl_mbox/evt.rs b/embassy-stm32/src/tl_mbox/evt.rs index 47a8b72fd..77ce7b4ca 100644 --- a/embassy-stm32/src/tl_mbox/evt.rs +++ b/embassy-stm32/src/tl_mbox/evt.rs | |||
| @@ -2,11 +2,13 @@ use core::mem::MaybeUninit; | |||
| 2 | 2 | ||
| 3 | use super::cmd::{AclDataPacket, AclDataSerial}; | 3 | use super::cmd::{AclDataPacket, AclDataSerial}; |
| 4 | use super::consts::TlPacketType; | 4 | use super::consts::TlPacketType; |
| 5 | use super::mm::MemoryManager; | ||
| 5 | use super::{PacketHeader, TL_EVT_HEADER_SIZE}; | 6 | use super::{PacketHeader, TL_EVT_HEADER_SIZE}; |
| 6 | use crate::tl_mbox::mm::MemoryManager; | ||
| 7 | 7 | ||
| 8 | /// the payload of [`Evt`] for a command status event | 8 | /** |
| 9 | #[derive(Copy, Clone)] | 9 | * The payload of `Evt` for a command status event |
| 10 | */ | ||
| 11 | #[derive(Debug, Copy, Clone)] | ||
| 10 | #[repr(C, packed)] | 12 | #[repr(C, packed)] |
| 11 | pub struct CsEvt { | 13 | pub struct CsEvt { |
| 12 | pub status: u8, | 14 | pub status: u8, |
| @@ -14,16 +16,39 @@ pub struct CsEvt { | |||
| 14 | pub cmd_code: u16, | 16 | pub cmd_code: u16, |
| 15 | } | 17 | } |
| 16 | 18 | ||
| 17 | /// the payload of [`Evt`] for a command complete event | 19 | /** |
| 18 | #[derive(Clone, Copy, Default)] | 20 | * The payload of `Evt` for a command complete event |
| 21 | */ | ||
| 22 | #[derive(Debug, Copy, Clone, Default)] | ||
| 19 | #[repr(C, packed)] | 23 | #[repr(C, packed)] |
| 20 | pub struct CcEvt { | 24 | pub struct CcEvt { |
| 21 | pub num_cmd: u8, | 25 | pub num_cmd: u8, |
| 22 | pub cmd_code: u8, | 26 | pub cmd_code: u16, |
| 23 | pub payload: [u8; 1], | 27 | pub payload: [u8; 1], |
| 24 | } | 28 | } |
| 25 | 29 | ||
| 26 | #[derive(Clone, Copy, Default)] | 30 | impl CcEvt { |
| 31 | pub fn write(&self, buf: &mut [u8]) { | ||
| 32 | unsafe { | ||
| 33 | let len = core::mem::size_of::<CcEvt>(); | ||
| 34 | assert!(buf.len() >= len); | ||
| 35 | |||
| 36 | let self_ptr: *const CcEvt = self; | ||
| 37 | let self_buf_ptr: *const u8 = self_ptr.cast(); | ||
| 38 | |||
| 39 | core::ptr::copy(self_buf_ptr, buf.as_mut_ptr(), len); | ||
| 40 | } | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | #[derive(Debug, Copy, Clone, Default)] | ||
| 45 | #[repr(C, packed)] | ||
| 46 | pub struct AsynchEvt { | ||
| 47 | sub_evt_code: u16, | ||
| 48 | payload: [u8; 1], | ||
| 49 | } | ||
| 50 | |||
| 51 | #[derive(Debug, Copy, Clone, Default)] | ||
| 27 | #[repr(C, packed)] | 52 | #[repr(C, packed)] |
| 28 | pub struct Evt { | 53 | pub struct Evt { |
| 29 | pub evt_code: u8, | 54 | pub evt_code: u8, |
| @@ -31,7 +56,7 @@ pub struct Evt { | |||
| 31 | pub payload: [u8; 1], | 56 | pub payload: [u8; 1], |
| 32 | } | 57 | } |
| 33 | 58 | ||
| 34 | #[derive(Clone, Copy, Default)] | 59 | #[derive(Debug, Copy, Clone, Default)] |
| 35 | #[repr(C, packed)] | 60 | #[repr(C, packed)] |
| 36 | pub struct EvtSerial { | 61 | pub struct EvtSerial { |
| 37 | pub kind: u8, | 62 | pub kind: u8, |
| @@ -46,14 +71,26 @@ pub struct EvtSerial { | |||
| 46 | /// Be careful that the asynchronous events reported by the CPU2 on the system channel do | 71 | /// 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 | 72 | /// include the header and shall use `EvtPacket` format. Only the command response format on the |
| 48 | /// system channel is different. | 73 | /// system channel is different. |
| 49 | #[derive(Clone, Copy, Default)] | 74 | #[derive(Copy, Clone, Default)] |
| 50 | #[repr(C, packed)] | 75 | #[repr(C, packed)] |
| 51 | pub struct EvtPacket { | 76 | pub struct EvtPacket { |
| 52 | pub header: PacketHeader, | 77 | pub header: PacketHeader, |
| 53 | pub evt_serial: EvtSerial, | 78 | pub evt_serial: EvtSerial, |
| 54 | } | 79 | } |
| 55 | 80 | ||
| 56 | /// Smart pointer to the [`EvtPacket`] that will dispose of it automatically on drop | 81 | impl EvtPacket { |
| 82 | pub fn kind(&self) -> u8 { | ||
| 83 | self.evt_serial.kind | ||
| 84 | } | ||
| 85 | |||
| 86 | pub fn evt(&self) -> &Evt { | ||
| 87 | &self.evt_serial.evt | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | /// smart pointer to the [`EvtPacket`] that will dispose of [`EvtPacket`] buffer automatically | ||
| 92 | /// on [`Drop`] | ||
| 93 | #[derive(Debug)] | ||
| 57 | pub struct EvtBox { | 94 | pub struct EvtBox { |
| 58 | ptr: *mut EvtPacket, | 95 | ptr: *mut EvtPacket, |
| 59 | } | 96 | } |
| @@ -64,7 +101,7 @@ impl EvtBox { | |||
| 64 | Self { ptr } | 101 | Self { ptr } |
| 65 | } | 102 | } |
| 66 | 103 | ||
| 67 | /// Copies the event data from inner pointer and returns and event structure | 104 | /// copies event data from inner pointer and returns an event structure |
| 68 | pub fn evt(&self) -> EvtPacket { | 105 | pub fn evt(&self) -> EvtPacket { |
| 69 | let mut evt = MaybeUninit::uninit(); | 106 | let mut evt = MaybeUninit::uninit(); |
| 70 | unsafe { | 107 | unsafe { |
| @@ -73,28 +110,11 @@ impl EvtBox { | |||
| 73 | } | 110 | } |
| 74 | } | 111 | } |
| 75 | 112 | ||
| 76 | /// Returns the size of a buffer required to hold this event | 113 | /// writes an underlying [`EvtPacket`] into the provided buffer. |
| 77 | pub fn size(&self) -> Result<usize, ()> { | 114 | /// Returns the number of bytes that were written. |
| 78 | unsafe { | 115 | /// Returns an error if event kind is unknown or if provided buffer size is not enough. |
| 79 | let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; | 116 | #[allow(clippy::result_unit_err)] |
| 80 | 117 | pub fn write(&self, buf: &mut [u8]) -> Result<usize, ()> { | |
| 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 { | 118 | unsafe { |
| 99 | let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; | 119 | let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; |
| 100 | 120 | ||
| @@ -127,6 +147,26 @@ impl EvtBox { | |||
| 127 | } | 147 | } |
| 128 | } | 148 | } |
| 129 | } | 149 | } |
| 150 | |||
| 151 | /// returns the size of a buffer required to hold this event | ||
| 152 | #[allow(clippy::result_unit_err)] | ||
| 153 | pub fn size(&self) -> Result<usize, ()> { | ||
| 154 | unsafe { | ||
| 155 | let evt_kind = TlPacketType::try_from((*self.ptr).evt_serial.kind)?; | ||
| 156 | |||
| 157 | let evt_data: *const EvtPacket = self.ptr.cast(); | ||
| 158 | let evt_serial: *const EvtSerial = &(*evt_data).evt_serial; | ||
| 159 | |||
| 160 | let acl_data: *const AclDataPacket = self.ptr.cast(); | ||
| 161 | let acl_serial: *const AclDataSerial = &(*acl_data).acl_data_serial; | ||
| 162 | |||
| 163 | if let TlPacketType::AclData = evt_kind { | ||
| 164 | Ok((*acl_serial).length as usize + 5) | ||
| 165 | } else { | ||
| 166 | Ok((*evt_serial).evt.payload_len as usize + TL_EVT_HEADER_SIZE) | ||
| 167 | } | ||
| 168 | } | ||
| 169 | } | ||
| 130 | } | 170 | } |
| 131 | 171 | ||
| 132 | impl Drop for EvtBox { | 172 | impl Drop for EvtBox { |
diff --git a/embassy-stm32/src/tl_mbox/hci.rs b/embassy-stm32/src/tl_mbox/hci.rs new file mode 100644 index 000000000..5bb4ba666 --- /dev/null +++ b/embassy-stm32/src/tl_mbox/hci.rs | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | use super::ble::Ble; | ||
| 2 | use super::consts::TlPacketType; | ||
| 3 | use super::evt::CcEvt; | ||
| 4 | use super::shci::{shci_ble_init, ShciBleInitCmdParam}; | ||
| 5 | use super::{TlMbox, STATE}; | ||
| 6 | |||
| 7 | pub struct RadioCoprocessor<'d> { | ||
| 8 | mbox: TlMbox<'d>, | ||
| 9 | config: ShciBleInitCmdParam, | ||
| 10 | rx_buffer: [u8; 500], | ||
| 11 | } | ||
| 12 | |||
| 13 | impl<'d> RadioCoprocessor<'d> { | ||
| 14 | pub fn new(mbox: TlMbox<'d>, config: ShciBleInitCmdParam) -> Self { | ||
| 15 | Self { | ||
| 16 | mbox, | ||
| 17 | config, | ||
| 18 | rx_buffer: [0u8; 500], | ||
| 19 | } | ||
| 20 | } | ||
| 21 | |||
| 22 | pub fn write(&mut self, params: &[u8]) -> Result<(), ()> { | ||
| 23 | let cmd_code = params[0]; | ||
| 24 | let cmd = TlPacketType::try_from(cmd_code)?; | ||
| 25 | |||
| 26 | match cmd { | ||
| 27 | TlPacketType::BleCmd => Ble::send_cmd(params), | ||
| 28 | _ => todo!(), | ||
| 29 | } | ||
| 30 | |||
| 31 | Ok(()) | ||
| 32 | } | ||
| 33 | |||
| 34 | pub async fn read(&mut self) -> &[u8] { | ||
| 35 | self.rx_buffer = [0u8; 500]; | ||
| 36 | |||
| 37 | loop { | ||
| 38 | STATE.wait().await; | ||
| 39 | |||
| 40 | if let Some(evt) = self.mbox.dequeue_event() { | ||
| 41 | let event = evt.evt(); | ||
| 42 | evt.write(&mut self.rx_buffer).unwrap(); | ||
| 43 | |||
| 44 | if event.kind() == 18 { | ||
| 45 | shci_ble_init(self.config); | ||
| 46 | self.rx_buffer[0] = 0x04; // replace event code with one that is supported by HCI | ||
| 47 | } | ||
| 48 | |||
| 49 | if let Some(cc) = self.mbox.pop_last_cc_evt() { | ||
| 50 | |||
| 51 | |||
| 52 | continue; | ||
| 53 | } | ||
| 54 | |||
| 55 | let payload_len = self.rx_buffer[2]; | ||
| 56 | return &self.rx_buffer[..3 + payload_len as usize]; | ||
| 57 | } | ||
| 58 | } | ||
| 59 | } | ||
| 60 | } | ||
diff --git a/embassy-stm32/src/tl_mbox/mm.rs b/embassy-stm32/src/tl_mbox/mm.rs index e28a6aa0c..a40438499 100644 --- a/embassy-stm32/src/tl_mbox/mm.rs +++ b/embassy-stm32/src/tl_mbox/mm.rs | |||
| @@ -1,56 +1,57 @@ | |||
| 1 | //! Memory manager routines | ||
| 2 | |||
| 3 | use core::mem::MaybeUninit; | ||
| 4 | |||
| 1 | use super::evt::EvtPacket; | 5 | use super::evt::EvtPacket; |
| 6 | use super::ipcc::Ipcc; | ||
| 2 | use super::unsafe_linked_list::LinkedListNode; | 7 | use super::unsafe_linked_list::LinkedListNode; |
| 3 | use super::{ | 8 | use super::{ |
| 4 | channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUFF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, | 9 | channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, |
| 5 | SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, TL_REF_TABLE, | 10 | SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, TL_REF_TABLE, |
| 6 | }; | 11 | }; |
| 7 | use crate::tl_mbox::ipcc::Ipcc; | ||
| 8 | 12 | ||
| 9 | pub struct MemoryManager; | 13 | pub(super) struct MemoryManager; |
| 10 | 14 | ||
| 11 | impl MemoryManager { | 15 | impl MemoryManager { |
| 12 | pub fn enable() { | 16 | pub fn new() -> Self { |
| 13 | unsafe { | 17 | unsafe { |
| 14 | LinkedListNode::init_head(FREE_BUFF_QUEUE.as_mut_ptr()); | 18 | LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); |
| 15 | LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); | 19 | LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); |
| 16 | 20 | ||
| 17 | TL_MEM_MANAGER_TABLE.as_mut_ptr().write_volatile(MemManagerTable { | 21 | TL_MEM_MANAGER_TABLE = MaybeUninit::new(MemManagerTable { |
| 18 | spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), | 22 | spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), |
| 19 | spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), | 23 | spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), |
| 20 | ble_pool: EVT_POOL.as_ptr().cast(), | 24 | blepool: EVT_POOL.as_ptr().cast(), |
| 21 | ble_pool_size: POOL_SIZE as u32, | 25 | blepoolsize: POOL_SIZE as u32, |
| 22 | pevt_free_buffer_queue: FREE_BUFF_QUEUE.as_mut_ptr(), | 26 | pevt_free_buffer_queue: FREE_BUF_QUEUE.as_mut_ptr(), |
| 23 | traces_evt_pool: core::ptr::null(), | 27 | traces_evt_pool: core::ptr::null(), |
| 24 | traces_pool_size: 0, | 28 | tracespoolsize: 0, |
| 25 | }); | 29 | }); |
| 26 | } | 30 | } |
| 27 | } | ||
| 28 | 31 | ||
| 29 | pub fn evt_handler() { | 32 | MemoryManager |
| 30 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false); | ||
| 31 | Self::send_free_buf(); | ||
| 32 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); | ||
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | pub fn evt_drop(evt: *mut EvtPacket) { | 35 | pub fn evt_drop(evt: *mut EvtPacket) { |
| 36 | unsafe { | 36 | unsafe { |
| 37 | let list_node = evt.cast(); | 37 | let list_node = evt.cast(); |
| 38 | 38 | ||
| 39 | LinkedListNode::remove_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); | 39 | LinkedListNode::insert_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); |
| 40 | } | ||
| 41 | 40 | ||
| 42 | let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); | 41 | let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); |
| 43 | 42 | ||
| 44 | // postpone event buffer freeing to IPCC interrupt handler | 43 | // postpone event buffer freeing to IPCC interrupt handler |
| 45 | if channel_is_busy { | 44 | if channel_is_busy { |
| 46 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); | 45 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); |
| 47 | } else { | 46 | } else { |
| 48 | Self::send_free_buf(); | 47 | Self::send_free_buf(); |
| 49 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); | 48 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); |
| 49 | } | ||
| 50 | } | 50 | } |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | fn send_free_buf() { | 53 | /// gives free event buffers back to CPU2 from local buffer queue |
| 54 | pub fn send_free_buf() { | ||
| 54 | unsafe { | 55 | unsafe { |
| 55 | let mut node_ptr = core::ptr::null_mut(); | 56 | let mut node_ptr = core::ptr::null_mut(); |
| 56 | let node_ptr_ptr: *mut _ = &mut node_ptr; | 57 | let node_ptr_ptr: *mut _ = &mut node_ptr; |
| @@ -64,4 +65,11 @@ impl MemoryManager { | |||
| 64 | } | 65 | } |
| 65 | } | 66 | } |
| 66 | } | 67 | } |
| 68 | |||
| 69 | /// free buffer channel interrupt handler | ||
| 70 | pub fn free_buf_handler() { | ||
| 71 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false); | ||
| 72 | Self::send_free_buf(); | ||
| 73 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); | ||
| 74 | } | ||
| 67 | } | 75 | } |
diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32/src/tl_mbox/mod.rs index efbbf2d1d..21a954417 100644 --- a/embassy-stm32/src/tl_mbox/mod.rs +++ b/embassy-stm32/src/tl_mbox/mod.rs | |||
| @@ -1,79 +1,50 @@ | |||
| 1 | use core::mem::MaybeUninit; | 1 | use core::mem::MaybeUninit; |
| 2 | 2 | ||
| 3 | use atomic_polyfill::{compiler_fence, Ordering}; | ||
| 4 | use bit_field::BitField; | 3 | use bit_field::BitField; |
| 5 | use embassy_cortex_m::interrupt::Interrupt; | 4 | use embassy_cortex_m::interrupt::Interrupt; |
| 5 | use embassy_futures::block_on; | ||
| 6 | use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; | 6 | use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; |
| 7 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 7 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 8 | use embassy_sync::channel::Channel; | 8 | use embassy_sync::channel::Channel; |
| 9 | use embassy_sync::signal::Signal; | ||
| 9 | 10 | ||
| 10 | use self::ble::Ble; | ||
| 11 | use self::cmd::{AclDataPacket, CmdPacket}; | 11 | use self::cmd::{AclDataPacket, CmdPacket}; |
| 12 | use self::evt::{CsEvt, EvtBox}; | 12 | use self::evt::{CcEvt, EvtBox}; |
| 13 | use self::mm::MemoryManager; | 13 | use self::ipcc::{Config, Ipcc}; |
| 14 | use self::shci::{shci_ble_init, ShciBleInitCmdParam}; | ||
| 15 | use self::sys::Sys; | ||
| 16 | use self::unsafe_linked_list::LinkedListNode; | 14 | use self::unsafe_linked_list::LinkedListNode; |
| 17 | use crate::interrupt; | 15 | use crate::interrupt; |
| 18 | use crate::peripherals::IPCC; | 16 | use crate::peripherals::IPCC; |
| 19 | pub use crate::tl_mbox::ipcc::Config; | ||
| 20 | use crate::tl_mbox::ipcc::Ipcc; | ||
| 21 | |||
| 22 | mod ble; | ||
| 23 | mod channels; | ||
| 24 | mod cmd; | ||
| 25 | mod consts; | ||
| 26 | mod evt; | ||
| 27 | mod ipcc; | ||
| 28 | mod mm; | ||
| 29 | mod shci; | ||
| 30 | mod sys; | ||
| 31 | mod unsafe_linked_list; | ||
| 32 | |||
| 33 | pub type PacketHeader = LinkedListNode; | ||
| 34 | 17 | ||
| 35 | const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::<PacketHeader>(); | 18 | pub mod ble; |
| 36 | const TL_EVT_HEADER_SIZE: usize = 3; | 19 | pub mod channels; |
| 37 | const TL_CS_EVT_SIZE: usize = core::mem::size_of::<CsEvt>(); | 20 | pub mod cmd; |
| 38 | 21 | pub mod consts; | |
| 39 | const CFG_TL_BLE_EVT_QUEUE_LENGTH: usize = 5; | 22 | pub mod evt; |
| 40 | const CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255; | 23 | pub mod hci; |
| 41 | const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE; | 24 | pub mod ipcc; |
| 42 | 25 | pub mod mm; | |
| 43 | const POOL_SIZE: usize = CFG_TL_BLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); | 26 | pub mod shci; |
| 44 | 27 | pub mod sys; | |
| 45 | const fn divc(x: usize, y: usize) -> usize { | 28 | pub mod unsafe_linked_list; |
| 46 | (x + y - 1) / y | ||
| 47 | } | ||
| 48 | |||
| 49 | #[repr(C, packed)] | ||
| 50 | #[derive(Copy, Clone)] | ||
| 51 | pub struct SafeBootInfoTable { | ||
| 52 | version: u32, | ||
| 53 | } | ||
| 54 | |||
| 55 | #[repr(C, packed)] | ||
| 56 | #[derive(Copy, Clone)] | ||
| 57 | pub struct FusInfoTable { | ||
| 58 | version: u32, | ||
| 59 | memory_size: u32, | ||
| 60 | fus_info: u32, | ||
| 61 | } | ||
| 62 | 29 | ||
| 63 | /// Interrupt handler. | 30 | /// Interrupt handler. |
| 64 | pub struct ReceiveInterruptHandler {} | 31 | pub struct ReceiveInterruptHandler {} |
| 65 | 32 | ||
| 66 | impl interrupt::Handler<interrupt::IPCC_C1_RX> for ReceiveInterruptHandler { | 33 | impl interrupt::Handler<interrupt::IPCC_C1_RX> for ReceiveInterruptHandler { |
| 67 | unsafe fn on_interrupt() { | 34 | unsafe fn on_interrupt() { |
| 68 | // info!("ipcc rx interrupt"); | 35 | debug!("ipcc rx interrupt"); |
| 69 | 36 | ||
| 70 | if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { | 37 | if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { |
| 38 | debug!("sys evt"); | ||
| 71 | sys::Sys::evt_handler(); | 39 | sys::Sys::evt_handler(); |
| 72 | } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) { | 40 | } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) { |
| 41 | debug!("ble evt"); | ||
| 73 | ble::Ble::evt_handler(); | 42 | ble::Ble::evt_handler(); |
| 74 | } else { | 43 | } else { |
| 75 | todo!() | 44 | todo!() |
| 76 | } | 45 | } |
| 46 | |||
| 47 | STATE.signal(()); | ||
| 77 | } | 48 | } |
| 78 | } | 49 | } |
| 79 | 50 | ||
| @@ -81,37 +52,62 @@ pub struct TransmitInterruptHandler {} | |||
| 81 | 52 | ||
| 82 | impl interrupt::Handler<interrupt::IPCC_C1_TX> for TransmitInterruptHandler { | 53 | impl interrupt::Handler<interrupt::IPCC_C1_TX> for TransmitInterruptHandler { |
| 83 | unsafe fn on_interrupt() { | 54 | unsafe fn on_interrupt() { |
| 84 | // info!("ipcc tx interrupt"); | 55 | debug!("ipcc tx interrupt"); |
| 85 | 56 | ||
| 86 | if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { | 57 | if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { |
| 58 | debug!("sys cmd rsp"); | ||
| 87 | // TODO: handle this case | 59 | // TODO: handle this case |
| 88 | let _ = sys::Sys::cmd_evt_handler(); | 60 | let cc = sys::Sys::cmd_evt_handler(); |
| 61 | let a = unsafe { core::slice::from_raw_parts(&cc as *const _ as *const u8, core::mem::size_of::<CcEvt>()) }; | ||
| 62 | debug!("{:#04x}", a); | ||
| 63 | |||
| 64 | LAST_CC_EVT.signal(cc); | ||
| 89 | } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) { | 65 | } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) { |
| 90 | mm::MemoryManager::evt_handler(); | 66 | debug!("mm"); |
| 67 | mm::MemoryManager::free_buf_handler(); | ||
| 91 | } else { | 68 | } else { |
| 92 | todo!() | 69 | todo!() |
| 93 | } | 70 | } |
| 71 | |||
| 72 | STATE.signal(()); | ||
| 94 | } | 73 | } |
| 95 | } | 74 | } |
| 96 | 75 | ||
| 97 | /// # Version | 76 | #[derive(Debug, Copy, Clone)] |
| 98 | /// - 0 -> 3 = Build - 0: Untracked - 15:Released - x: Tracked version | 77 | #[repr(C, packed)] |
| 99 | /// - 4 -> 7 = branch - 0: Mass Market - x: ... | 78 | pub struct SafeBootInfoTable { |
| 100 | /// - 8 -> 15 = Subversion | 79 | version: u32, |
| 101 | /// - 16 -> 23 = Version minor | 80 | } |
| 102 | /// - 24 -> 31 = Version major | 81 | |
| 103 | /// # Memory Size | 82 | #[derive(Debug, Copy, Clone)] |
| 104 | /// - 0 -> 7 = Flash ( Number of 4k sector) | 83 | #[repr(C, packed)] |
| 105 | /// - 8 -> 15 = Reserved ( Shall be set to 0 - may be used as flash extension ) | 84 | pub struct RssInfoTable { |
| 106 | /// - 16 -> 23 = SRAM2b ( Number of 1k sector) | 85 | version: u32, |
| 107 | /// - 24 -> 31 = SRAM2a ( Number of 1k sector) | 86 | memory_size: u32, |
| 87 | rss_info: u32, | ||
| 88 | } | ||
| 89 | |||
| 90 | /** | ||
| 91 | * Version | ||
| 92 | * [0:3] = Build - 0: Untracked - 15:Released - x: Tracked version | ||
| 93 | * [4:7] = branch - 0: Mass Market - x: ... | ||
| 94 | * [8:15] = Subversion | ||
| 95 | * [16:23] = Version minor | ||
| 96 | * [24:31] = Version major | ||
| 97 | * | ||
| 98 | * Memory Size | ||
| 99 | * [0:7] = Flash ( Number of 4k sector) | ||
| 100 | * [8:15] = Reserved ( Shall be set to 0 - may be used as flash extension ) | ||
| 101 | * [16:23] = SRAM2b ( Number of 1k sector) | ||
| 102 | * [24:31] = SRAM2a ( Number of 1k sector) | ||
| 103 | */ | ||
| 104 | #[derive(Debug, Copy, Clone)] | ||
| 108 | #[repr(C, packed)] | 105 | #[repr(C, packed)] |
| 109 | #[derive(Copy, Clone)] | ||
| 110 | pub struct WirelessFwInfoTable { | 106 | pub struct WirelessFwInfoTable { |
| 111 | version: u32, | 107 | version: u32, |
| 112 | memory_size: u32, | 108 | memory_size: u32, |
| 113 | info_stack: u32, | 109 | thread_info: u32, |
| 114 | reserved: u32, | 110 | ble_info: u32, |
| 115 | } | 111 | } |
| 116 | 112 | ||
| 117 | impl WirelessFwInfoTable { | 113 | impl WirelessFwInfoTable { |
| @@ -122,42 +118,43 @@ impl WirelessFwInfoTable { | |||
| 122 | 118 | ||
| 123 | pub fn version_minor(&self) -> u8 { | 119 | pub fn version_minor(&self) -> u8 { |
| 124 | let version = self.version; | 120 | let version = self.version; |
| 125 | (version.get_bits(16..23) & 0xff) as u8 | 121 | (version.clone().get_bits(16..23) & 0xff) as u8 |
| 126 | } | 122 | } |
| 127 | 123 | ||
| 128 | pub fn subversion(&self) -> u8 { | 124 | pub fn subversion(&self) -> u8 { |
| 129 | let version = self.version; | 125 | let version = self.version; |
| 130 | (version.get_bits(8..15) & 0xff) as u8 | 126 | (version.clone().get_bits(8..15) & 0xff) as u8 |
| 131 | } | 127 | } |
| 132 | 128 | ||
| 133 | /// size of FLASH, expressed in number of 4K sectors | 129 | /// Size of FLASH, expressed in number of 4K sectors. |
| 134 | pub fn flash_size(&self) -> u8 { | 130 | pub fn flash_size(&self) -> u8 { |
| 135 | let memory_size = self.memory_size; | 131 | let memory_size = self.memory_size; |
| 136 | (memory_size.get_bits(0..7) & 0xff) as u8 | 132 | (memory_size.clone().get_bits(0..7) & 0xff) as u8 |
| 137 | } | 133 | } |
| 138 | 134 | ||
| 139 | /// size for SRAM2a, expressed in number of 1K sectors | 135 | /// Size of SRAM2a, expressed in number of 1K sectors. |
| 140 | pub fn sram2a_size(&self) -> u8 { | 136 | pub fn sram2a_size(&self) -> u8 { |
| 141 | let memory_size = self.memory_size; | 137 | let memory_size = self.memory_size; |
| 142 | (memory_size.get_bits(24..31) & 0xff) as u8 | 138 | (memory_size.clone().get_bits(24..31) & 0xff) as u8 |
| 143 | } | 139 | } |
| 144 | 140 | ||
| 145 | /// size of SRAM2b, expressed in number of 1K sectors | 141 | /// Size of SRAM2b, expressed in number of 1K sectors. |
| 146 | pub fn sram2b_size(&self) -> u8 { | 142 | pub fn sram2b_size(&self) -> u8 { |
| 147 | let memory_size = self.memory_size; | 143 | let memory_size = self.memory_size; |
| 148 | (memory_size.get_bits(16..23) & 0xff) as u8 | 144 | (memory_size.clone().get_bits(16..23) & 0xff) as u8 |
| 149 | } | 145 | } |
| 150 | } | 146 | } |
| 151 | 147 | ||
| 152 | #[repr(C, packed)] | 148 | #[derive(Debug, Clone)] |
| 153 | #[derive(Copy, Clone)] | 149 | #[repr(C, align(4))] |
| 154 | pub struct DeviceInfoTable { | 150 | pub struct DeviceInfoTable { |
| 155 | pub safe_boot_info_table: SafeBootInfoTable, | 151 | pub safe_boot_info_table: SafeBootInfoTable, |
| 156 | pub fus_info_table: FusInfoTable, | 152 | pub rss_info_table: RssInfoTable, |
| 157 | pub wireless_fw_info_table: WirelessFwInfoTable, | 153 | pub wireless_fw_info_table: WirelessFwInfoTable, |
| 158 | } | 154 | } |
| 159 | 155 | ||
| 160 | #[repr(C, packed)] | 156 | #[derive(Debug)] |
| 157 | #[repr(C, align(4))] | ||
| 161 | struct BleTable { | 158 | struct BleTable { |
| 162 | pcmd_buffer: *mut CmdPacket, | 159 | pcmd_buffer: *mut CmdPacket, |
| 163 | pcs_buffer: *const u8, | 160 | pcs_buffer: *const u8, |
| @@ -165,81 +162,86 @@ struct BleTable { | |||
| 165 | phci_acl_data_buffer: *mut AclDataPacket, | 162 | phci_acl_data_buffer: *mut AclDataPacket, |
| 166 | } | 163 | } |
| 167 | 164 | ||
| 168 | #[repr(C, packed)] | 165 | #[derive(Debug)] |
| 166 | #[repr(C, align(4))] | ||
| 169 | struct ThreadTable { | 167 | struct ThreadTable { |
| 170 | no_stack_buffer: *const u8, | 168 | nostack_buffer: *const u8, |
| 171 | cli_cmd_rsp_buffer: *const u8, | 169 | clicmdrsp_buffer: *const u8, |
| 172 | ot_cmd_rsp_buffer: *const u8, | 170 | otcmdrsp_buffer: *const u8, |
| 173 | } | 171 | } |
| 174 | 172 | ||
| 175 | #[repr(C, packed)] | 173 | // TODO: use later |
| 176 | struct SysTable { | 174 | #[derive(Debug)] |
| 177 | pcmd_buffer: *mut CmdPacket, | 175 | #[repr(C, align(4))] |
| 178 | sys_queue: *const LinkedListNode, | 176 | pub struct LldTestsTable { |
| 179 | } | 177 | clicmdrsp_buffer: *const u8, |
| 180 | 178 | m0cmd_buffer: *const u8, | |
| 181 | #[allow(dead_code)] // Not used currently but reserved | ||
| 182 | #[repr(C, packed)] | ||
| 183 | struct LldTestTable { | ||
| 184 | cli_cmd_rsp_buffer: *const u8, | ||
| 185 | m0_cmd_buffer: *const u8, | ||
| 186 | } | 179 | } |
| 187 | 180 | ||
| 188 | #[allow(dead_code)] // Not used currently but reserved | 181 | // TODO: use later |
| 189 | #[repr(C, packed)] | 182 | #[derive(Debug)] |
| 190 | struct BleLldTable { | 183 | #[repr(C, align(4))] |
| 191 | cmd_rsp_buffer: *const u8, | 184 | pub struct BleLldTable { |
| 192 | m0_cmd_buffer: *const u8, | 185 | cmdrsp_buffer: *const u8, |
| 186 | m0cmd_buffer: *const u8, | ||
| 193 | } | 187 | } |
| 194 | 188 | ||
| 195 | #[allow(dead_code)] // Not used currently but reserved | 189 | // TODO: use later |
| 196 | #[repr(C, packed)] | 190 | #[derive(Debug)] |
| 197 | struct ZigbeeTable { | 191 | #[repr(C, align(4))] |
| 192 | pub struct ZigbeeTable { | ||
| 198 | notif_m0_to_m4_buffer: *const u8, | 193 | notif_m0_to_m4_buffer: *const u8, |
| 199 | appli_cmd_m4_to_m0_buffer: *const u8, | 194 | appli_cmd_m4_to_m0_bufer: *const u8, |
| 200 | request_m0_to_m4_buffer: *const u8, | 195 | request_m0_to_m4_buffer: *const u8, |
| 201 | } | 196 | } |
| 202 | 197 | ||
| 203 | #[repr(C, packed)] | 198 | #[derive(Debug)] |
| 199 | #[repr(C, align(4))] | ||
| 200 | struct SysTable { | ||
| 201 | pcmd_buffer: *mut CmdPacket, | ||
| 202 | sys_queue: *const LinkedListNode, | ||
| 203 | } | ||
| 204 | |||
| 205 | #[derive(Debug)] | ||
| 206 | #[repr(C, align(4))] | ||
| 204 | struct MemManagerTable { | 207 | struct MemManagerTable { |
| 205 | spare_ble_buffer: *const u8, | 208 | spare_ble_buffer: *const u8, |
| 206 | spare_sys_buffer: *const u8, | 209 | spare_sys_buffer: *const u8, |
| 207 | 210 | ||
| 208 | ble_pool: *const u8, | 211 | blepool: *const u8, |
| 209 | ble_pool_size: u32, | 212 | blepoolsize: u32, |
| 210 | 213 | ||
| 211 | pevt_free_buffer_queue: *mut LinkedListNode, | 214 | pevt_free_buffer_queue: *mut LinkedListNode, |
| 212 | 215 | ||
| 213 | traces_evt_pool: *const u8, | 216 | traces_evt_pool: *const u8, |
| 214 | traces_pool_size: u32, | 217 | tracespoolsize: u32, |
| 215 | } | 218 | } |
| 216 | 219 | ||
| 217 | #[repr(C, packed)] | 220 | #[derive(Debug)] |
| 221 | #[repr(C, align(4))] | ||
| 218 | struct TracesTable { | 222 | struct TracesTable { |
| 219 | traces_queue: *const u8, | 223 | traces_queue: *const u8, |
| 220 | } | 224 | } |
| 221 | 225 | ||
| 222 | #[repr(C, packed)] | 226 | #[derive(Debug)] |
| 227 | #[repr(C, align(4))] | ||
| 223 | struct Mac802_15_4Table { | 228 | struct Mac802_15_4Table { |
| 224 | pcmd_rsp_buffer: *const u8, | 229 | p_cmdrsp_buffer: *const u8, |
| 225 | pnotack_buffer: *const u8, | 230 | p_notack_buffer: *const u8, |
| 226 | evt_queue: *const u8, | 231 | evt_queue: *const u8, |
| 227 | } | 232 | } |
| 228 | 233 | ||
| 229 | /// reference table. Contains pointers to all other tables | 234 | /// Reference table. Contains pointers to all other tables. |
| 230 | #[repr(C, packed)] | 235 | #[derive(Debug, Copy, Clone)] |
| 231 | #[derive(Copy, Clone)] | 236 | #[repr(C)] |
| 232 | pub struct RefTable { | 237 | pub struct RefTable { |
| 233 | pub device_info_table: *const DeviceInfoTable, | 238 | device_info_table: *const DeviceInfoTable, |
| 234 | ble_table: *const BleTable, | 239 | ble_table: *const BleTable, |
| 235 | thread_table: *const ThreadTable, | 240 | thread_table: *const ThreadTable, |
| 236 | sys_table: *const SysTable, | 241 | sys_table: *const SysTable, |
| 237 | mem_manager_table: *const MemManagerTable, | 242 | mem_manager_table: *const MemManagerTable, |
| 238 | traces_table: *const TracesTable, | 243 | traces_table: *const TracesTable, |
| 239 | mac_802_15_4_table: *const Mac802_15_4Table, | 244 | mac_802_15_4_table: *const Mac802_15_4Table, |
| 240 | zigbee_table: *const ZigbeeTable, | ||
| 241 | lld_tests_table: *const LldTestTable, | ||
| 242 | ble_lld_table: *const BleLldTable, | ||
| 243 | } | 245 | } |
| 244 | 246 | ||
| 245 | #[link_section = "TL_REF_TABLE"] | 247 | #[link_section = "TL_REF_TABLE"] |
| @@ -255,12 +257,6 @@ static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit(); | |||
| 255 | static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit(); | 257 | static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit(); |
| 256 | 258 | ||
| 257 | #[link_section = "MB_MEM1"] | 259 | #[link_section = "MB_MEM1"] |
| 258 | static mut TL_LLD_TESTS_TABLE: MaybeUninit<LldTestTable> = MaybeUninit::uninit(); | ||
| 259 | |||
| 260 | #[link_section = "MB_MEM1"] | ||
| 261 | static mut TL_BLE_LLD_TABLE: MaybeUninit<BleLldTable> = MaybeUninit::uninit(); | ||
| 262 | |||
| 263 | #[link_section = "MB_MEM1"] | ||
| 264 | static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit(); | 260 | static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit(); |
| 265 | 261 | ||
| 266 | #[link_section = "MB_MEM1"] | 262 | #[link_section = "MB_MEM1"] |
| @@ -272,15 +268,21 @@ static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit(); | |||
| 272 | #[link_section = "MB_MEM1"] | 268 | #[link_section = "MB_MEM1"] |
| 273 | static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit(); | 269 | static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit(); |
| 274 | 270 | ||
| 275 | #[link_section = "MB_MEM1"] | 271 | #[link_section = "MB_MEM2"] |
| 276 | static mut TL_ZIGBEE_TABLE: MaybeUninit<ZigbeeTable> = MaybeUninit::uninit(); | 272 | static mut FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); |
| 273 | |||
| 274 | // Not in shared RAM | ||
| 275 | static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 277 | 276 | ||
| 278 | #[allow(dead_code)] // Not used currently but reserved | 277 | #[allow(dead_code)] // Not used currently but reserved |
| 279 | #[link_section = "MB_MEM1"] | 278 | #[link_section = "MB_MEM2"] |
| 280 | static mut FREE_BUFF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | 279 | static mut TRACES_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); |
| 281 | 280 | ||
| 282 | // not in shared RAM | 281 | type PacketHeader = LinkedListNode; |
| 283 | static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | 282 | |
| 283 | const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::<PacketHeader>(); | ||
| 284 | const TL_EVT_HEADER_SIZE: usize = 3; | ||
| 285 | const TL_CS_EVT_SIZE: usize = core::mem::size_of::<evt::CsEvt>(); | ||
| 284 | 286 | ||
| 285 | #[link_section = "MB_MEM2"] | 287 | #[link_section = "MB_MEM2"] |
| 286 | static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> = | 288 | static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> = |
| @@ -293,7 +295,30 @@ static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | |||
| 293 | static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | 295 | static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); |
| 294 | 296 | ||
| 295 | #[link_section = "MB_MEM2"] | 297 | #[link_section = "MB_MEM2"] |
| 296 | static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); | 298 | pub static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); |
| 299 | |||
| 300 | /** | ||
| 301 | * Queue length of BLE Event | ||
| 302 | * This parameter defines the number of asynchronous events that can be stored in the HCI layer before | ||
| 303 | * being reported to the application. When a command is sent to the BLE core coprocessor, the HCI layer | ||
| 304 | * is waiting for the event with the Num_HCI_Command_Packets set to 1. The receive queue shall be large | ||
| 305 | * enough to store all asynchronous events received in between. | ||
| 306 | * When CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE is set to 27, this allow to store three 255 bytes long asynchronous events | ||
| 307 | * between the HCI command and its event. | ||
| 308 | * This parameter depends on the value given to CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE. When the queue size is to small, | ||
| 309 | * the system may hang if the queue is full with asynchronous events and the HCI layer is still waiting | ||
| 310 | * for a CC/CS event, In that case, the notification TL_BLE_HCI_ToNot() is called to indicate | ||
| 311 | * to the application a HCI command did not receive its command event within 30s (Default HCI Timeout). | ||
| 312 | */ | ||
| 313 | const CFG_TLBLE_EVT_QUEUE_LENGTH: usize = 5; | ||
| 314 | const CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255; | ||
| 315 | const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE; | ||
| 316 | |||
| 317 | const fn divc(x: usize, y: usize) -> usize { | ||
| 318 | ((x) + (y) - 1) / (y) | ||
| 319 | } | ||
| 320 | |||
| 321 | const POOL_SIZE: usize = CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); | ||
| 297 | 322 | ||
| 298 | #[link_section = "MB_MEM2"] | 323 | #[link_section = "MB_MEM2"] |
| 299 | static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit(); | 324 | static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit(); |
| @@ -310,18 +335,27 @@ static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HE | |||
| 310 | static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); | 335 | static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); |
| 311 | 336 | ||
| 312 | #[link_section = "MB_MEM2"] | 337 | #[link_section = "MB_MEM2"] |
| 313 | // "magic" numbers from ST ---v---v | 338 | // fuck these "magic" numbers from ST ---v---v |
| 314 | static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); | 339 | static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); |
| 315 | 340 | ||
| 316 | // TODO: get a better size, this is a placeholder | 341 | static HEAPLESS_EVT_QUEUE: Channel<CriticalSectionRawMutex, EvtBox, 32> = Channel::new(); |
| 317 | pub(crate) static TL_CHANNEL: Channel<CriticalSectionRawMutex, EvtBox, 5> = Channel::new(); | 342 | |
| 343 | static STATE: Signal<CriticalSectionRawMutex, ()> = Signal::new(); | ||
| 344 | |||
| 345 | /// current event that is produced during IPCC IRQ handler execution | ||
| 346 | /// on SYS channel | ||
| 347 | /// last received Command Complete event | ||
| 348 | static LAST_CC_EVT: Signal<CriticalSectionRawMutex, CcEvt> = Signal::new(); | ||
| 318 | 349 | ||
| 319 | pub struct TlMbox<'d> { | 350 | pub struct TlMbox<'d> { |
| 351 | sys: sys::Sys, | ||
| 352 | ble: ble::Ble, | ||
| 353 | _mm: mm::MemoryManager, | ||
| 354 | |||
| 320 | _ipcc: PeripheralRef<'d, IPCC>, | 355 | _ipcc: PeripheralRef<'d, IPCC>, |
| 321 | } | 356 | } |
| 322 | 357 | ||
| 323 | impl<'d> TlMbox<'d> { | 358 | impl<'d> TlMbox<'d> { |
| 324 | /// initializes low-level transport between CPU1 and BLE stack on CPU2 | ||
| 325 | pub fn new( | 359 | pub fn new( |
| 326 | ipcc: impl Peripheral<P = IPCC> + 'd, | 360 | ipcc: impl Peripheral<P = IPCC> + 'd, |
| 327 | _irqs: impl interrupt::Binding<interrupt::IPCC_C1_RX, ReceiveInterruptHandler> | 361 | _irqs: impl interrupt::Binding<interrupt::IPCC_C1_RX, ReceiveInterruptHandler> |
| @@ -331,25 +365,16 @@ impl<'d> TlMbox<'d> { | |||
| 331 | into_ref!(ipcc); | 365 | into_ref!(ipcc); |
| 332 | 366 | ||
| 333 | unsafe { | 367 | unsafe { |
| 334 | compiler_fence(Ordering::AcqRel); | ||
| 335 | |||
| 336 | TL_REF_TABLE.as_mut_ptr().write_volatile(RefTable { | 368 | TL_REF_TABLE.as_mut_ptr().write_volatile(RefTable { |
| 337 | device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(), | 369 | device_info_table: TL_DEVICE_INFO_TABLE.as_mut_ptr(), |
| 338 | ble_table: TL_BLE_TABLE.as_ptr(), | 370 | ble_table: TL_BLE_TABLE.as_ptr(), |
| 339 | thread_table: TL_THREAD_TABLE.as_ptr(), | 371 | thread_table: TL_THREAD_TABLE.as_ptr(), |
| 340 | sys_table: TL_SYS_TABLE.as_ptr(), | 372 | sys_table: TL_SYS_TABLE.as_ptr(), |
| 341 | mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), | 373 | mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), |
| 342 | traces_table: TL_TRACES_TABLE.as_ptr(), | 374 | traces_table: TL_TRACES_TABLE.as_ptr(), |
| 343 | mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), | 375 | mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), |
| 344 | zigbee_table: TL_ZIGBEE_TABLE.as_ptr(), | ||
| 345 | lld_tests_table: TL_LLD_TESTS_TABLE.as_ptr(), | ||
| 346 | ble_lld_table: TL_BLE_LLD_TABLE.as_ptr(), | ||
| 347 | }); | 376 | }); |
| 348 | 377 | ||
| 349 | // info!("TL_REF_TABLE addr: {:x}", TL_REF_TABLE.as_ptr() as usize); | ||
| 350 | |||
| 351 | compiler_fence(Ordering::AcqRel); | ||
| 352 | |||
| 353 | TL_SYS_TABLE = MaybeUninit::zeroed(); | 378 | TL_SYS_TABLE = MaybeUninit::zeroed(); |
| 354 | TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed(); | 379 | TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed(); |
| 355 | TL_BLE_TABLE = MaybeUninit::zeroed(); | 380 | TL_BLE_TABLE = MaybeUninit::zeroed(); |
| @@ -357,9 +382,6 @@ impl<'d> TlMbox<'d> { | |||
| 357 | TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed(); | 382 | TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed(); |
| 358 | TL_TRACES_TABLE = MaybeUninit::zeroed(); | 383 | TL_TRACES_TABLE = MaybeUninit::zeroed(); |
| 359 | TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed(); | 384 | TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed(); |
| 360 | TL_ZIGBEE_TABLE = MaybeUninit::zeroed(); | ||
| 361 | TL_LLD_TESTS_TABLE = MaybeUninit::zeroed(); | ||
| 362 | TL_BLE_LLD_TABLE = MaybeUninit::zeroed(); | ||
| 363 | 385 | ||
| 364 | EVT_POOL = MaybeUninit::zeroed(); | 386 | EVT_POOL = MaybeUninit::zeroed(); |
| 365 | SYS_SPARE_EVT_BUF = MaybeUninit::zeroed(); | 387 | SYS_SPARE_EVT_BUF = MaybeUninit::zeroed(); |
| @@ -368,15 +390,13 @@ impl<'d> TlMbox<'d> { | |||
| 368 | CS_BUFFER = MaybeUninit::zeroed(); | 390 | CS_BUFFER = MaybeUninit::zeroed(); |
| 369 | BLE_CMD_BUFFER = MaybeUninit::zeroed(); | 391 | BLE_CMD_BUFFER = MaybeUninit::zeroed(); |
| 370 | HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed(); | 392 | HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed(); |
| 371 | |||
| 372 | compiler_fence(Ordering::AcqRel); | ||
| 373 | } | 393 | } |
| 374 | 394 | ||
| 375 | Ipcc::enable(config); | 395 | Ipcc::enable(config); |
| 376 | 396 | ||
| 377 | Sys::enable(); | 397 | let sys = sys::Sys::new(); |
| 378 | Ble::enable(); | 398 | let ble = ble::Ble::new(); |
| 379 | MemoryManager::enable(); | 399 | let mm = mm::MemoryManager::new(); |
| 380 | 400 | ||
| 381 | // enable interrupts | 401 | // enable interrupts |
| 382 | crate::interrupt::IPCC_C1_RX::unpend(); | 402 | crate::interrupt::IPCC_C1_RX::unpend(); |
| @@ -385,13 +405,19 @@ impl<'d> TlMbox<'d> { | |||
| 385 | unsafe { crate::interrupt::IPCC_C1_RX::enable() }; | 405 | unsafe { crate::interrupt::IPCC_C1_RX::enable() }; |
| 386 | unsafe { crate::interrupt::IPCC_C1_TX::enable() }; | 406 | unsafe { crate::interrupt::IPCC_C1_TX::enable() }; |
| 387 | 407 | ||
| 388 | Self { _ipcc: ipcc } | 408 | Self { |
| 409 | sys, | ||
| 410 | ble, | ||
| 411 | _mm: mm, | ||
| 412 | _ipcc: ipcc, | ||
| 413 | } | ||
| 389 | } | 414 | } |
| 390 | 415 | ||
| 416 | /// Returns CPU2 wireless firmware information (if present). | ||
| 391 | pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> { | 417 | pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> { |
| 392 | let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table }; | 418 | let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table }; |
| 393 | 419 | ||
| 394 | // zero version indicates that CPU2 wasn't active and didn't fill the information table | 420 | // Zero version indicates that CPU2 wasn't active and didn't fill the information table |
| 395 | if info.version != 0 { | 421 | if info.version != 0 { |
| 396 | Some(*info) | 422 | Some(*info) |
| 397 | } else { | 423 | } else { |
| @@ -399,19 +425,22 @@ impl<'d> TlMbox<'d> { | |||
| 399 | } | 425 | } |
| 400 | } | 426 | } |
| 401 | 427 | ||
| 402 | pub fn shci_ble_init(&self, param: ShciBleInitCmdParam) { | 428 | /// picks single [`EvtBox`] from internal event queue. |
| 403 | shci_ble_init(param); | 429 | /// |
| 430 | /// Internal event queu is populated in IPCC_RX_IRQ handler | ||
| 431 | pub fn dequeue_event(&mut self) -> Option<EvtBox> { | ||
| 432 | HEAPLESS_EVT_QUEUE.try_recv().ok() | ||
| 404 | } | 433 | } |
| 405 | 434 | ||
| 406 | pub fn send_ble_cmd(&self, buf: &[u8]) { | 435 | /// retrieves last Command Complete event and removes it from mailbox |
| 407 | ble::Ble::send_cmd(buf); | 436 | pub fn pop_last_cc_evt(&mut self) -> Option<CcEvt> { |
| 408 | } | 437 | if LAST_CC_EVT.signaled() { |
| 409 | 438 | let cc = Some(block_on(LAST_CC_EVT.wait())); | |
| 410 | // pub fn send_sys_cmd(&self, buf: &[u8]) { | 439 | LAST_CC_EVT.reset(); |
| 411 | // sys::Sys::send_cmd(buf); | ||
| 412 | // } | ||
| 413 | 440 | ||
| 414 | pub async fn read(&self) -> EvtBox { | 441 | cc |
| 415 | TL_CHANNEL.recv().await | 442 | } else { |
| 443 | None | ||
| 444 | } | ||
| 416 | } | 445 | } |
| 417 | } | 446 | } |
diff --git a/embassy-stm32/src/tl_mbox/shci.rs b/embassy-stm32/src/tl_mbox/shci.rs index 6b5b2dd19..b19baa702 100644 --- a/embassy-stm32/src/tl_mbox/shci.rs +++ b/embassy-stm32/src/tl_mbox/shci.rs | |||
| @@ -1,16 +1,10 @@ | |||
| 1 | //! HCI commands for system channel | ||
| 2 | |||
| 3 | use super::cmd::CmdPacket; | 1 | use super::cmd::CmdPacket; |
| 4 | use super::consts::TlPacketType; | 2 | use super::consts::TlPacketType; |
| 5 | use super::{channels, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE}; | 3 | use super::{sys, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE}; |
| 6 | use crate::tl_mbox::ipcc::Ipcc; | ||
| 7 | 4 | ||
| 8 | const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66; | 5 | 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 | 6 | ||
| 13 | #[derive(Clone, Copy)] | 7 | #[derive(Debug, Clone, Copy)] |
| 14 | #[repr(C, packed)] | 8 | #[repr(C, packed)] |
| 15 | pub struct ShciBleInitCmdParam { | 9 | pub struct ShciBleInitCmdParam { |
| 16 | /// NOT USED CURRENTLY | 10 | /// NOT USED CURRENTLY |
| @@ -63,39 +57,44 @@ impl Default for ShciBleInitCmdParam { | |||
| 63 | } | 57 | } |
| 64 | } | 58 | } |
| 65 | 59 | ||
| 66 | #[derive(Clone, Copy, Default)] | 60 | #[derive(Debug, Clone, Copy, Default)] |
| 67 | #[repr(C, packed)] | 61 | #[repr(C, packed)] |
| 68 | pub struct ShciHeader { | 62 | pub struct ShciHeader { |
| 69 | metadata: [u32; 3], | 63 | metadata: [u32; 3], |
| 70 | } | 64 | } |
| 71 | 65 | ||
| 72 | #[derive(Clone, Copy)] | 66 | #[derive(Debug, Clone, Copy)] |
| 73 | #[repr(C, packed)] | 67 | #[repr(C, packed)] |
| 74 | pub struct ShciBleInitCmdPacket { | 68 | pub struct ShciBleInitCmdPacket { |
| 75 | header: ShciHeader, | 69 | header: ShciHeader, |
| 76 | param: ShciBleInitCmdParam, | 70 | param: ShciBleInitCmdParam, |
| 77 | } | 71 | } |
| 78 | 72 | ||
| 73 | pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE; | ||
| 74 | #[allow(dead_code)] // Not used currently but reserved | ||
| 75 | const TL_BLE_EVT_CS_BUFFER_SIZE: usize = TL_PACKET_HEADER_SIZE + TL_BLE_EVT_CS_PACKET_SIZE; | ||
| 76 | |||
| 79 | pub fn shci_ble_init(param: ShciBleInitCmdParam) { | 77 | pub fn shci_ble_init(param: ShciBleInitCmdParam) { |
| 78 | debug!("shci init"); | ||
| 79 | |||
| 80 | let mut packet = ShciBleInitCmdPacket { | 80 | let mut packet = ShciBleInitCmdPacket { |
| 81 | header: ShciHeader::default(), | 81 | header: ShciHeader::default(), |
| 82 | param, | 82 | param, |
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| 85 | let packet_ptr: *mut ShciBleInitCmdPacket = &mut packet; | 85 | let packet_ptr: *mut _ = &mut packet; |
| 86 | 86 | ||
| 87 | unsafe { | 87 | unsafe { |
| 88 | let cmd_ptr: *mut CmdPacket = packet_ptr.cast(); | 88 | let cmd_ptr: *mut CmdPacket = packet_ptr.cast(); |
| 89 | 89 | ||
| 90 | (*cmd_ptr).cmd_serial.cmd.cmd_code = SCHI_OPCODE_BLE_INIT; | 90 | (*cmd_ptr).cmdserial.cmd.cmd_code = SCHI_OPCODE_BLE_INIT; |
| 91 | (*cmd_ptr).cmd_serial.cmd.payload_len = core::mem::size_of::<ShciBleInitCmdParam>() as u8; | 91 | (*cmd_ptr).cmdserial.cmd.payload_len = core::mem::size_of::<ShciBleInitCmdParam>() as u8; |
| 92 | 92 | ||
| 93 | let cmd_buf = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; | 93 | let mut p_cmd_buffer = &mut *(*TL_SYS_TABLE.as_mut_ptr()).pcmd_buffer; |
| 94 | core::ptr::write(cmd_buf, *cmd_ptr); | 94 | core::ptr::write(p_cmd_buffer, *cmd_ptr); |
| 95 | 95 | ||
| 96 | cmd_buf.cmd_serial.ty = TlPacketType::SysCmd as u8; | 96 | p_cmd_buffer.cmdserial.ty = TlPacketType::SysCmd as u8; |
| 97 | 97 | ||
| 98 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); | 98 | sys::send_cmd(); |
| 99 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); | ||
| 100 | } | 99 | } |
| 101 | } | 100 | } |
diff --git a/embassy-stm32/src/tl_mbox/sys.rs b/embassy-stm32/src/tl_mbox/sys.rs index 9685fb920..c87aa440c 100644 --- a/embassy-stm32/src/tl_mbox/sys.rs +++ b/embassy-stm32/src/tl_mbox/sys.rs | |||
| @@ -1,45 +1,27 @@ | |||
| 1 | use embassy_futures::block_on; | 1 | use embassy_futures::block_on; |
| 2 | 2 | ||
| 3 | use super::cmd::{CmdPacket, CmdSerial}; | 3 | use super::cmd::{CmdPacket, CmdSerial}; |
| 4 | use super::consts::TlPacketType; | ||
| 5 | use super::evt::{CcEvt, EvtBox, EvtSerial}; | 4 | use super::evt::{CcEvt, EvtBox, EvtSerial}; |
| 5 | use super::ipcc::Ipcc; | ||
| 6 | use super::unsafe_linked_list::LinkedListNode; | 6 | use super::unsafe_linked_list::LinkedListNode; |
| 7 | use super::{channels, SysTable, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_CHANNEL, TL_REF_TABLE, TL_SYS_TABLE}; | 7 | use super::{channels, SysTable, HEAPLESS_EVT_QUEUE, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; |
| 8 | use crate::tl_mbox::ipcc::Ipcc; | ||
| 9 | 8 | ||
| 10 | pub struct Sys; | 9 | pub struct Sys; |
| 11 | 10 | ||
| 12 | impl Sys { | 11 | impl Sys { |
| 13 | pub fn enable() { | 12 | pub fn new() -> Self { |
| 14 | unsafe { | 13 | unsafe { |
| 15 | LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); | 14 | LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); |
| 16 | 15 | ||
| 17 | TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { | 16 | TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { |
| 18 | pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), | 17 | pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), |
| 19 | sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), | 18 | sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), |
| 20 | }); | 19 | }) |
| 21 | } | 20 | } |
| 22 | 21 | ||
| 23 | Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true); | 22 | Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true); |
| 24 | } | ||
| 25 | |||
| 26 | pub fn evt_handler() { | ||
| 27 | unsafe { | ||
| 28 | let mut node_ptr = core::ptr::null_mut(); | ||
| 29 | let node_ptr_ptr: *mut _ = &mut node_ptr; | ||
| 30 | |||
| 31 | while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { | ||
| 32 | LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); | ||
| 33 | |||
| 34 | let event = node_ptr.cast(); | ||
| 35 | let event = EvtBox::new(event); | ||
| 36 | |||
| 37 | // TODO: not really happy about this | ||
| 38 | block_on(TL_CHANNEL.send(event)); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | 23 | ||
| 42 | Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); | 24 | Sys |
| 43 | } | 25 | } |
| 44 | 26 | ||
| 45 | pub fn cmd_evt_handler() -> CcEvt { | 27 | pub fn cmd_evt_handler() -> CcEvt { |
| @@ -55,29 +37,40 @@ impl Sys { | |||
| 55 | // 4. CcEvt type is the actual SHCI response | 37 | // 4. CcEvt type is the actual SHCI response |
| 56 | // 5. profit | 38 | // 5. profit |
| 57 | unsafe { | 39 | unsafe { |
| 58 | let cmd: *const CmdPacket = (*TL_SYS_TABLE.as_ptr()).pcmd_buffer; | 40 | let pcmd: *const CmdPacket = (*TL_SYS_TABLE.as_ptr()).pcmd_buffer; |
| 59 | let cmd_serial: *const CmdSerial = &(*cmd).cmd_serial; | 41 | |
| 42 | let a = unsafe { | ||
| 43 | core::slice::from_raw_parts(&pcmd as *const _ as *const u8, core::mem::size_of::<CmdPacket>()) | ||
| 44 | }; | ||
| 45 | debug!("shci response {:#04x}", a); | ||
| 46 | |||
| 47 | let cmd_serial: *const CmdSerial = &(*pcmd).cmdserial; | ||
| 60 | let evt_serial: *const EvtSerial = cmd_serial.cast(); | 48 | let evt_serial: *const EvtSerial = cmd_serial.cast(); |
| 61 | let cc = (*evt_serial).evt.payload.as_ptr().cast(); | 49 | let cc: *const CcEvt = (*evt_serial).evt.payload.as_ptr().cast(); |
| 62 | *cc | 50 | *cc |
| 63 | } | 51 | } |
| 64 | } | 52 | } |
| 65 | 53 | ||
| 66 | #[allow(dead_code)] | 54 | pub fn evt_handler() { |
| 67 | pub fn send_cmd(buf: &[u8]) { | ||
| 68 | unsafe { | 55 | unsafe { |
| 69 | // TODO: check this | 56 | let mut node_ptr = core::ptr::null_mut(); |
| 70 | let cmd_buffer = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer; | 57 | let node_ptr_ptr: *mut _ = &mut node_ptr; |
| 71 | let cmd_serial: *mut CmdSerial = &mut cmd_buffer.cmd_serial; | ||
| 72 | let cmd_serial_buf = cmd_serial.cast(); | ||
| 73 | 58 | ||
| 74 | core::ptr::copy(buf.as_ptr(), cmd_serial_buf, buf.len()); | 59 | while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { |
| 60 | LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); | ||
| 75 | 61 | ||
| 76 | let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer; | 62 | let event = node_ptr.cast(); |
| 77 | cmd_packet.cmd_serial.ty = TlPacketType::SysCmd as u8; | 63 | let event = EvtBox::new(event); |
| 78 | 64 | ||
| 79 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); | 65 | block_on(HEAPLESS_EVT_QUEUE.send(event)); |
| 80 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); | 66 | } |
| 81 | } | 67 | } |
| 68 | |||
| 69 | Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); | ||
| 82 | } | 70 | } |
| 83 | } | 71 | } |
| 72 | |||
| 73 | pub fn send_cmd() { | ||
| 74 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); | ||
| 75 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); | ||
| 76 | } | ||
diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs index 1724d946f..0525d3f37 100644 --- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs +++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs | |||
| @@ -4,7 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::tl_mbox::{Config, TlMbox}; | 7 | use embassy_stm32::tl_mbox::hci::RadioCoprocessor; |
| 8 | use embassy_stm32::tl_mbox::ipcc::Config; | ||
| 9 | use embassy_stm32::tl_mbox::TlMbox; | ||
| 8 | use embassy_stm32::{bind_interrupts, tl_mbox}; | 10 | use embassy_stm32::{bind_interrupts, tl_mbox}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 12 | ||
| @@ -45,53 +47,14 @@ async fn main(_spawner: Spawner) { | |||
| 45 | let config = Config::default(); | 47 | let config = Config::default(); |
| 46 | let mbox = TlMbox::new(p.IPCC, Irqs, config); | 48 | let mbox = TlMbox::new(p.IPCC, Irqs, config); |
| 47 | 49 | ||
| 48 | info!("waiting for coprocessor to boot"); | 50 | let mut rc = RadioCoprocessor::new(mbox, Default::default()); |
| 49 | let event_box = mbox.read().await; | 51 | rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]).unwrap(); |
| 50 | 52 | ||
| 51 | let mut payload = [0u8; 6]; | 53 | let response = rc.read().await; |
| 52 | event_box.copy_into_slice(&mut payload).unwrap(); | 54 | info!("coprocessor ready {}", response); |
| 53 | 55 | ||
| 54 | let event_packet = event_box.evt(); | 56 | let response = rc.read().await; |
| 55 | let kind = event_packet.evt_serial.kind; | 57 | info!("coprocessor ready {}", response); |
| 56 | |||
| 57 | // means recieved SYS event, which indicates in this case that the coprocessor is ready | ||
| 58 | if kind == 0x12 { | ||
| 59 | let code = event_packet.evt_serial.evt.evt_code; | ||
| 60 | let payload_len = event_packet.evt_serial.evt.payload_len; | ||
| 61 | |||
| 62 | info!( | ||
| 63 | "==> kind: {:#04x}, code: {:#04x}, payload_length: {}, payload: {:#04x}", | ||
| 64 | kind, | ||
| 65 | code, | ||
| 66 | payload_len, | ||
| 67 | payload[3..] | ||
| 68 | ); | ||
| 69 | } | ||
| 70 | |||
| 71 | // initialize ble stack, does not return a response | ||
| 72 | mbox.shci_ble_init(Default::default()); | ||
| 73 | |||
| 74 | info!("resetting BLE"); | ||
| 75 | mbox.send_ble_cmd(&[0x01, 0x03, 0x0c, 0x00, 0x00]); | ||
| 76 | |||
| 77 | let event_box = mbox.read().await; | ||
| 78 | |||
| 79 | let mut payload = [0u8; 7]; | ||
| 80 | event_box.copy_into_slice(&mut payload).unwrap(); | ||
| 81 | |||
| 82 | let event_packet = event_box.evt(); | ||
| 83 | let kind = event_packet.evt_serial.kind; | ||
| 84 | |||
| 85 | let code = event_packet.evt_serial.evt.evt_code; | ||
| 86 | let payload_len = event_packet.evt_serial.evt.payload_len; | ||
| 87 | |||
| 88 | info!( | ||
| 89 | "==> kind: {:#04x}, code: {:#04x}, payload_length: {}, payload: {:#04x}", | ||
| 90 | kind, | ||
| 91 | code, | ||
| 92 | payload_len, | ||
| 93 | payload[3..] | ||
| 94 | ); | ||
| 95 | 58 | ||
| 96 | info!("Test OK"); | 59 | info!("Test OK"); |
| 97 | cortex_m::asm::bkpt(); | 60 | cortex_m::asm::bkpt(); |
