diff options
| author | xoviat <[email protected]> | 2023-06-12 20:26:38 -0500 |
|---|---|---|
| committer | xoviat <[email protected]> | 2023-06-12 20:26:38 -0500 |
| commit | 7f63fbbf4a7acf258198010930a6b45435fc0e57 (patch) | |
| tree | 8b11dd462938caf0fafd08386da8e901eaee757e | |
| parent | c822fd46e558fc694bbec3358f31076e89d99164 (diff) | |
| parent | bf32dc5d3acee1f73fe445976bde474ffa6d04e0 (diff) | |
Merge branch 'old_tl_mbox' of github.com:OueslatiGhaith/embassy into old-tl-mbox
25 files changed, 1200 insertions, 724 deletions
diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml new file mode 100644 index 000000000..058d0e29f --- /dev/null +++ b/embassy-stm32-wpan/Cargo.toml | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | [package] | ||
| 2 | name = "embassy-stm32-wpan" | ||
| 3 | version = "0.1.0" | ||
| 4 | edition = "2021" | ||
| 5 | license = "MIT OR Apache-2.0" | ||
| 6 | |||
| 7 | [dependencies] | ||
| 8 | embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" } | ||
| 9 | embassy-sync = { version = "0.2.0", path = "../embassy-sync" } | ||
| 10 | embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } | ||
| 11 | embassy-futures = { version = "0.1.0", path = "../embassy-futures" } | ||
| 12 | embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } | ||
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } | ||
| 14 | |||
| 15 | defmt = { version = "0.3", optional = true } | ||
| 16 | cortex-m = "0.7.6" | ||
| 17 | heapless = "0.7.16" | ||
| 18 | |||
| 19 | bit_field = "0.10.2" | ||
| 20 | |||
| 21 | [features] | ||
| 22 | defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt"] | ||
| 23 | |||
| 24 | stm32wb10cc = [ "embassy-stm32/stm32wb10cc" ] | ||
| 25 | stm32wb15cc = [ "embassy-stm32/stm32wb15cc" ] | ||
| 26 | stm32wb30ce = [ "embassy-stm32/stm32wb30ce" ] | ||
| 27 | stm32wb35cc = [ "embassy-stm32/stm32wb35cc" ] | ||
| 28 | stm32wb35ce = [ "embassy-stm32/stm32wb35ce" ] | ||
| 29 | stm32wb50cg = [ "embassy-stm32/stm32wb50cg" ] | ||
| 30 | stm32wb55cc = [ "embassy-stm32/stm32wb55cc" ] | ||
| 31 | stm32wb55ce = [ "embassy-stm32/stm32wb55ce" ] | ||
| 32 | stm32wb55cg = [ "embassy-stm32/stm32wb55cg" ] | ||
| 33 | stm32wb55rc = [ "embassy-stm32/stm32wb55rc" ] | ||
| 34 | stm32wb55re = [ "embassy-stm32/stm32wb55re" ] | ||
| 35 | stm32wb55rg = [ "embassy-stm32/stm32wb55rg" ] | ||
| 36 | stm32wb55vc = [ "embassy-stm32/stm32wb55vc" ] | ||
| 37 | stm32wb55ve = [ "embassy-stm32/stm32wb55ve" ] | ||
| 38 | stm32wb55vg = [ "embassy-stm32/stm32wb55vg" ] | ||
| 39 | stm32wb55vy = [ "embassy-stm32/stm32wb55vy" ] \ No newline at end of file | ||
diff --git a/embassy-stm32-wpan/build.rs b/embassy-stm32-wpan/build.rs new file mode 100644 index 000000000..4edf73d59 --- /dev/null +++ b/embassy-stm32-wpan/build.rs | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | use std::env; | ||
| 2 | |||
| 3 | fn main() { | ||
| 4 | match env::vars() | ||
| 5 | .map(|(a, _)| a) | ||
| 6 | .filter(|x| x.starts_with("CARGO_FEATURE_STM32")) | ||
| 7 | .get_one() | ||
| 8 | { | ||
| 9 | Ok(_) => {} | ||
| 10 | Err(GetOneError::None) => panic!("No stm32xx Cargo feature enabled"), | ||
| 11 | Err(GetOneError::Multiple) => panic!("Multiple stm32xx Cargo features enabled"), | ||
| 12 | } | ||
| 13 | } | ||
| 14 | |||
| 15 | enum GetOneError { | ||
| 16 | None, | ||
| 17 | Multiple, | ||
| 18 | } | ||
| 19 | |||
| 20 | trait IteratorExt: Iterator { | ||
| 21 | fn get_one(self) -> Result<Self::Item, GetOneError>; | ||
| 22 | } | ||
| 23 | |||
| 24 | impl<T: Iterator> IteratorExt for T { | ||
| 25 | fn get_one(mut self) -> Result<Self::Item, GetOneError> { | ||
| 26 | match self.next() { | ||
| 27 | None => Err(GetOneError::None), | ||
| 28 | Some(res) => match self.next() { | ||
| 29 | Some(_) => Err(GetOneError::Multiple), | ||
| 30 | None => Ok(res), | ||
| 31 | }, | ||
| 32 | } | ||
| 33 | } | ||
| 34 | } | ||
diff --git a/embassy-stm32/src/tl_mbox/ble.rs b/embassy-stm32-wpan/src/ble.rs index 062377999..19955a8a3 100644 --- a/embassy-stm32/src/tl_mbox/ble.rs +++ b/embassy-stm32-wpan/src/ble.rs | |||
| @@ -1,26 +1,26 @@ | |||
| 1 | use embassy_futures::block_on; | 1 | use core::mem::MaybeUninit; |
| 2 | 2 | ||
| 3 | use super::cmd::CmdSerial; | 3 | use embassy_stm32::ipcc::Ipcc; |
| 4 | use super::consts::TlPacketType; | 4 | |
| 5 | use super::evt::EvtBox; | 5 | use crate::cmd::{CmdPacket, CmdSerial}; |
| 6 | use super::unsafe_linked_list::LinkedListNode; | 6 | use crate::consts::TlPacketType; |
| 7 | use super::{ | 7 | use crate::evt::EvtBox; |
| 8 | channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE, TL_CHANNEL, | 8 | use crate::tables::BleTable; |
| 9 | TL_REF_TABLE, | 9 | use crate::unsafe_linked_list::LinkedListNode; |
| 10 | use crate::{ | ||
| 11 | channels, BLE_CMD_BUFFER, CS_BUFFER, EVT_CHANNEL, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE, TL_REF_TABLE, | ||
| 10 | }; | 12 | }; |
| 11 | use crate::tl_mbox::cmd::CmdPacket; | ||
| 12 | use crate::tl_mbox::ipcc::Ipcc; | ||
| 13 | 13 | ||
| 14 | pub struct Ble; | 14 | pub struct Ble; |
| 15 | 15 | ||
| 16 | impl Ble { | 16 | impl Ble { |
| 17 | pub fn enable() { | 17 | pub(super) fn enable() { |
| 18 | unsafe { | 18 | unsafe { |
| 19 | LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); | 19 | LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); |
| 20 | 20 | ||
| 21 | TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable { | 21 | TL_BLE_TABLE = MaybeUninit::new(BleTable { |
| 22 | pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), | 22 | pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), |
| 23 | pcs_buffer: CS_BUFFER.as_mut_ptr().cast(), | 23 | pcs_buffer: CS_BUFFER.as_ptr().cast(), |
| 24 | pevt_queue: EVT_QUEUE.as_ptr().cast(), | 24 | pevt_queue: EVT_QUEUE.as_ptr().cast(), |
| 25 | phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(), | 25 | phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(), |
| 26 | }); | 26 | }); |
| @@ -29,7 +29,7 @@ impl Ble { | |||
| 29 | Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true); | 29 | Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | pub fn evt_handler() { | 32 | pub(super) fn evt_handler() { |
| 33 | unsafe { | 33 | unsafe { |
| 34 | let mut node_ptr = core::ptr::null_mut(); | 34 | let mut node_ptr = core::ptr::null_mut(); |
| 35 | let node_ptr_ptr: *mut _ = &mut node_ptr; | 35 | let node_ptr_ptr: *mut _ = &mut node_ptr; |
| @@ -40,25 +40,43 @@ impl Ble { | |||
| 40 | let event = node_ptr.cast(); | 40 | let event = node_ptr.cast(); |
| 41 | let event = EvtBox::new(event); | 41 | let event = EvtBox::new(event); |
| 42 | 42 | ||
| 43 | block_on(TL_CHANNEL.send(event)); | 43 | EVT_CHANNEL.try_send(event).unwrap(); |
| 44 | } | 44 | } |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL); | 47 | Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL); |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | pub fn send_cmd(buf: &[u8]) { | 50 | pub(super) fn acl_data_handler() { |
| 51 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, false); | ||
| 52 | |||
| 53 | // TODO: ACL data ack to the user | ||
| 54 | } | ||
| 55 | |||
| 56 | pub fn ble_send_cmd(buf: &[u8]) { | ||
| 57 | debug!("writing ble cmd"); | ||
| 58 | |||
| 51 | unsafe { | 59 | unsafe { |
| 52 | let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; | 60 | 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; | 61 | let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmdserial; |
| 54 | let pcmd_serial_buf: *mut u8 = pcmd_serial.cast(); | 62 | let pcmd_serial_buf: *mut u8 = pcmd_serial.cast(); |
| 55 | 63 | ||
| 56 | core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len()); | 64 | core::ptr::copy(buf.as_ptr(), pcmd_serial_buf, buf.len()); |
| 57 | 65 | ||
| 58 | let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; | 66 | let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; |
| 59 | cmd_packet.cmd_serial.ty = TlPacketType::BleCmd as u8; | 67 | cmd_packet.cmdserial.ty = TlPacketType::BleCmd as u8; |
| 60 | } | 68 | } |
| 61 | 69 | ||
| 62 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL); | 70 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL); |
| 63 | } | 71 | } |
| 72 | |||
| 73 | #[allow(dead_code)] // Not used currently but reserved | ||
| 74 | pub(super) fn ble_send_acl_data() { | ||
| 75 | let cmd_packet = unsafe { &mut *(*TL_REF_TABLE.assume_init().ble_table).phci_acl_data_buffer }; | ||
| 76 | |||
| 77 | cmd_packet.acl_data_serial.ty = TlPacketType::AclData as u8; | ||
| 78 | |||
| 79 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL); | ||
| 80 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL, true); | ||
| 81 | } | ||
| 64 | } | 82 | } |
diff --git a/embassy-stm32/src/tl_mbox/channels.rs b/embassy-stm32-wpan/src/channels.rs index 25a065ba4..9a2be1cfa 100644 --- a/embassy-stm32/src/tl_mbox/channels.rs +++ b/embassy-stm32-wpan/src/channels.rs | |||
| @@ -50,36 +50,30 @@ | |||
| 50 | //! | 50 | //! |
| 51 | 51 | ||
| 52 | pub mod cpu1 { | 52 | pub mod cpu1 { |
| 53 | use crate::tl_mbox::ipcc::IpccChannel; | 53 | use embassy_stm32::ipcc::IpccChannel; |
| 54 | 54 | ||
| 55 | // Not used currently but reserved | ||
| 56 | pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1; | 55 | pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1; |
| 57 | // Not used currently but reserved | ||
| 58 | pub const IPCC_SYSTEM_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel2; | 56 | pub const IPCC_SYSTEM_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel2; |
| 59 | #[allow(dead_code)] // Not used currently but reserved | ||
| 60 | pub const IPCC_THREAD_OT_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; | 57 | pub const IPCC_THREAD_OT_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; |
| 61 | #[allow(dead_code)] // Not used currently but reserved | 58 | #[allow(dead_code)] // Not used currently but reserved |
| 62 | pub const IPCC_ZIGBEE_CMD_APPLI_CHANNEL: IpccChannel = IpccChannel::Channel3; | 59 | pub const IPCC_ZIGBEE_CMD_APPLI_CHANNEL: IpccChannel = IpccChannel::Channel3; |
| 63 | #[allow(dead_code)] // Not used currently but reserved | 60 | #[allow(dead_code)] // Not used currently but reserved |
| 64 | pub const IPCC_MAC_802_15_4_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; | 61 | pub const IPCC_MAC_802_15_4_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3; |
| 65 | // Not used currently but reserved | ||
| 66 | pub const IPCC_MM_RELEASE_BUFFER_CHANNEL: IpccChannel = IpccChannel::Channel4; | ||
| 67 | #[allow(dead_code)] // Not used currently but reserved | 62 | #[allow(dead_code)] // Not used currently but reserved |
| 63 | pub const IPCC_MM_RELEASE_BUFFER_CHANNEL: IpccChannel = IpccChannel::Channel4; | ||
| 68 | pub const IPCC_THREAD_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; | 64 | pub const IPCC_THREAD_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; |
| 69 | #[allow(dead_code)] // Not used currently but reserved | 65 | #[allow(dead_code)] // Not used currently but reserved |
| 70 | pub const IPCC_LLDTESTS_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; | 66 | pub const IPCC_LLDTESTS_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; |
| 71 | #[allow(dead_code)] // Not used currently but reserved | 67 | #[allow(dead_code)] // Not used currently but reserved |
| 72 | pub const IPCC_BLE_LLD_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; | 68 | pub const IPCC_BLE_LLD_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5; |
| 73 | #[allow(dead_code)] // Not used currently but reserved | ||
| 74 | pub const IPCC_HCI_ACL_DATA_CHANNEL: IpccChannel = IpccChannel::Channel6; | 69 | pub const IPCC_HCI_ACL_DATA_CHANNEL: IpccChannel = IpccChannel::Channel6; |
| 75 | } | 70 | } |
| 76 | 71 | ||
| 77 | pub mod cpu2 { | 72 | pub mod cpu2 { |
| 78 | use crate::tl_mbox::ipcc::IpccChannel; | 73 | use embassy_stm32::ipcc::IpccChannel; |
| 79 | 74 | ||
| 80 | pub const IPCC_BLE_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel1; | 75 | pub const IPCC_BLE_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel1; |
| 81 | pub const IPCC_SYSTEM_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel2; | 76 | pub const IPCC_SYSTEM_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel2; |
| 82 | #[allow(dead_code)] // Not used currently but reserved | ||
| 83 | pub const IPCC_THREAD_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3; | 77 | pub const IPCC_THREAD_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3; |
| 84 | #[allow(dead_code)] // Not used currently but reserved | 78 | #[allow(dead_code)] // Not used currently but reserved |
| 85 | pub const IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3; | 79 | pub const IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3; |
| @@ -88,10 +82,8 @@ pub mod cpu2 { | |||
| 88 | #[allow(dead_code)] // Not used currently but reserved | 82 | #[allow(dead_code)] // Not used currently but reserved |
| 89 | pub const IPCC_LDDTESTS_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; | 83 | pub const IPCC_LDDTESTS_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; |
| 90 | #[allow(dead_code)] // Not used currently but reserved | 84 | #[allow(dead_code)] // Not used currently but reserved |
| 91 | pub const IPCC_BLE_LLD_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; | 85 | pub const IPCC_BLE_LLDÇM0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3; |
| 92 | #[allow(dead_code)] // Not used currently but reserved | ||
| 93 | pub const IPCC_TRACES_CHANNEL: IpccChannel = IpccChannel::Channel4; | 86 | pub const IPCC_TRACES_CHANNEL: IpccChannel = IpccChannel::Channel4; |
| 94 | #[allow(dead_code)] // Not used currently but reserved | ||
| 95 | pub const IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel5; | 87 | pub const IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel5; |
| 96 | #[allow(dead_code)] // Not used currently but reserved | 88 | #[allow(dead_code)] // Not used currently but reserved |
| 97 | pub const IPCC_LLDTESTS_CLI_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5; | 89 | pub const IPCC_LLDTESTS_CLI_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5; |
diff --git a/embassy-stm32-wpan/src/cmd.rs b/embassy-stm32-wpan/src/cmd.rs new file mode 100644 index 000000000..1f7dae7f7 --- /dev/null +++ b/embassy-stm32-wpan/src/cmd.rs | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | use crate::evt::{EvtPacket, EvtSerial}; | ||
| 2 | use crate::{PacketHeader, TL_EVT_HEADER_SIZE}; | ||
| 3 | |||
| 4 | #[derive(Copy, Clone)] | ||
| 5 | #[repr(C, packed)] | ||
| 6 | pub struct Cmd { | ||
| 7 | pub cmd_code: u16, | ||
| 8 | pub payload_len: u8, | ||
| 9 | pub payload: [u8; 255], | ||
| 10 | } | ||
| 11 | |||
| 12 | impl Default for Cmd { | ||
| 13 | fn default() -> Self { | ||
| 14 | Self { | ||
| 15 | cmd_code: 0, | ||
| 16 | payload_len: 0, | ||
| 17 | payload: [0u8; 255], | ||
| 18 | } | ||
| 19 | } | ||
| 20 | } | ||
| 21 | |||
| 22 | #[derive(Copy, Clone, Default)] | ||
| 23 | #[repr(C, packed)] | ||
| 24 | pub struct CmdSerial { | ||
| 25 | pub ty: u8, | ||
| 26 | pub cmd: Cmd, | ||
| 27 | } | ||
| 28 | |||
| 29 | #[derive(Copy, Clone, Default)] | ||
| 30 | #[repr(C, packed)] | ||
| 31 | pub struct CmdPacket { | ||
| 32 | pub header: PacketHeader, | ||
| 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 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | #[derive(Copy, Clone)] | ||
| 64 | #[repr(C, packed)] | ||
| 65 | pub struct AclDataSerial { | ||
| 66 | pub ty: u8, | ||
| 67 | pub handle: u16, | ||
| 68 | pub length: u16, | ||
| 69 | pub acl_data: [u8; 1], | ||
| 70 | } | ||
| 71 | |||
| 72 | #[derive(Copy, Clone)] | ||
| 73 | #[repr(C, packed)] | ||
| 74 | pub struct AclDataPacket { | ||
| 75 | pub header: PacketHeader, | ||
| 76 | pub acl_data_serial: AclDataSerial, | ||
| 77 | } | ||
diff --git a/embassy-stm32/src/tl_mbox/consts.rs b/embassy-stm32-wpan/src/consts.rs index e16a26cd0..caf26c06b 100644 --- a/embassy-stm32/src/tl_mbox/consts.rs +++ b/embassy-stm32-wpan/src/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-wpan/src/evt.rs index 47a8b72fd..b53fe506e 100644 --- a/embassy-stm32/src/tl_mbox/evt.rs +++ b/embassy-stm32-wpan/src/evt.rs | |||
| @@ -3,9 +3,11 @@ use core::mem::MaybeUninit; | |||
| 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::{PacketHeader, TL_EVT_HEADER_SIZE}; | 5 | use super::{PacketHeader, TL_EVT_HEADER_SIZE}; |
| 6 | use crate::tl_mbox::mm::MemoryManager; | 6 | use crate::mm; |
| 7 | 7 | ||
| 8 | /// the payload of [`Evt`] for a command status event | 8 | /** |
| 9 | * The payload of `Evt` for a command status event | ||
| 10 | */ | ||
| 9 | #[derive(Copy, Clone)] | 11 | #[derive(Copy, Clone)] |
| 10 | #[repr(C, packed)] | 12 | #[repr(C, packed)] |
| 11 | pub struct CsEvt { | 13 | pub struct CsEvt { |
| @@ -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(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(Copy, Clone, Default)] | ||
| 45 | #[repr(C, packed)] | ||
| 46 | pub struct AsynchEvt { | ||
| 47 | sub_evt_code: u16, | ||
| 48 | payload: [u8; 1], | ||
| 49 | } | ||
| 50 | |||
| 51 | #[derive(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(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,10 +147,30 @@ 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 { |
| 133 | fn drop(&mut self) { | 173 | fn drop(&mut self) { |
| 134 | MemoryManager::evt_drop(self.ptr); | 174 | mm::MemoryManager::evt_drop(self.ptr); |
| 135 | } | 175 | } |
| 136 | } | 176 | } |
diff --git a/embassy-stm32-wpan/src/fmt.rs b/embassy-stm32-wpan/src/fmt.rs new file mode 100644 index 000000000..066970813 --- /dev/null +++ b/embassy-stm32-wpan/src/fmt.rs | |||
| @@ -0,0 +1,225 @@ | |||
| 1 | #![macro_use] | ||
| 2 | #![allow(unused_macros)] | ||
| 3 | |||
| 4 | #[cfg(all(feature = "defmt", feature = "log"))] | ||
| 5 | compile_error!("You may not enable both `defmt` and `log` features."); | ||
| 6 | |||
| 7 | macro_rules! assert { | ||
| 8 | ($($x:tt)*) => { | ||
| 9 | { | ||
| 10 | #[cfg(not(feature = "defmt"))] | ||
| 11 | ::core::assert!($($x)*); | ||
| 12 | #[cfg(feature = "defmt")] | ||
| 13 | ::defmt::assert!($($x)*); | ||
| 14 | } | ||
| 15 | }; | ||
| 16 | } | ||
| 17 | |||
| 18 | macro_rules! assert_eq { | ||
| 19 | ($($x:tt)*) => { | ||
| 20 | { | ||
| 21 | #[cfg(not(feature = "defmt"))] | ||
| 22 | ::core::assert_eq!($($x)*); | ||
| 23 | #[cfg(feature = "defmt")] | ||
| 24 | ::defmt::assert_eq!($($x)*); | ||
| 25 | } | ||
| 26 | }; | ||
| 27 | } | ||
| 28 | |||
| 29 | macro_rules! assert_ne { | ||
| 30 | ($($x:tt)*) => { | ||
| 31 | { | ||
| 32 | #[cfg(not(feature = "defmt"))] | ||
| 33 | ::core::assert_ne!($($x)*); | ||
| 34 | #[cfg(feature = "defmt")] | ||
| 35 | ::defmt::assert_ne!($($x)*); | ||
| 36 | } | ||
| 37 | }; | ||
| 38 | } | ||
| 39 | |||
| 40 | macro_rules! debug_assert { | ||
| 41 | ($($x:tt)*) => { | ||
| 42 | { | ||
| 43 | #[cfg(not(feature = "defmt"))] | ||
| 44 | ::core::debug_assert!($($x)*); | ||
| 45 | #[cfg(feature = "defmt")] | ||
| 46 | ::defmt::debug_assert!($($x)*); | ||
| 47 | } | ||
| 48 | }; | ||
| 49 | } | ||
| 50 | |||
| 51 | macro_rules! debug_assert_eq { | ||
| 52 | ($($x:tt)*) => { | ||
| 53 | { | ||
| 54 | #[cfg(not(feature = "defmt"))] | ||
| 55 | ::core::debug_assert_eq!($($x)*); | ||
| 56 | #[cfg(feature = "defmt")] | ||
| 57 | ::defmt::debug_assert_eq!($($x)*); | ||
| 58 | } | ||
| 59 | }; | ||
| 60 | } | ||
| 61 | |||
| 62 | macro_rules! debug_assert_ne { | ||
| 63 | ($($x:tt)*) => { | ||
| 64 | { | ||
| 65 | #[cfg(not(feature = "defmt"))] | ||
| 66 | ::core::debug_assert_ne!($($x)*); | ||
| 67 | #[cfg(feature = "defmt")] | ||
| 68 | ::defmt::debug_assert_ne!($($x)*); | ||
| 69 | } | ||
| 70 | }; | ||
| 71 | } | ||
| 72 | |||
| 73 | macro_rules! todo { | ||
| 74 | ($($x:tt)*) => { | ||
| 75 | { | ||
| 76 | #[cfg(not(feature = "defmt"))] | ||
| 77 | ::core::todo!($($x)*); | ||
| 78 | #[cfg(feature = "defmt")] | ||
| 79 | ::defmt::todo!($($x)*); | ||
| 80 | } | ||
| 81 | }; | ||
| 82 | } | ||
| 83 | |||
| 84 | macro_rules! unreachable { | ||
| 85 | ($($x:tt)*) => { | ||
| 86 | { | ||
| 87 | #[cfg(not(feature = "defmt"))] | ||
| 88 | ::core::unreachable!($($x)*); | ||
| 89 | #[cfg(feature = "defmt")] | ||
| 90 | ::defmt::unreachable!($($x)*); | ||
| 91 | } | ||
| 92 | }; | ||
| 93 | } | ||
| 94 | |||
| 95 | macro_rules! panic { | ||
| 96 | ($($x:tt)*) => { | ||
| 97 | { | ||
| 98 | #[cfg(not(feature = "defmt"))] | ||
| 99 | ::core::panic!($($x)*); | ||
| 100 | #[cfg(feature = "defmt")] | ||
| 101 | ::defmt::panic!($($x)*); | ||
| 102 | } | ||
| 103 | }; | ||
| 104 | } | ||
| 105 | |||
| 106 | macro_rules! trace { | ||
| 107 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 108 | { | ||
| 109 | #[cfg(feature = "log")] | ||
| 110 | ::log::trace!($s $(, $x)*); | ||
| 111 | #[cfg(feature = "defmt")] | ||
| 112 | ::defmt::trace!($s $(, $x)*); | ||
| 113 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 114 | let _ = ($( & $x ),*); | ||
| 115 | } | ||
| 116 | }; | ||
| 117 | } | ||
| 118 | |||
| 119 | macro_rules! debug { | ||
| 120 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 121 | { | ||
| 122 | #[cfg(feature = "log")] | ||
| 123 | ::log::debug!($s $(, $x)*); | ||
| 124 | #[cfg(feature = "defmt")] | ||
| 125 | ::defmt::debug!($s $(, $x)*); | ||
| 126 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 127 | let _ = ($( & $x ),*); | ||
| 128 | } | ||
| 129 | }; | ||
| 130 | } | ||
| 131 | |||
| 132 | macro_rules! info { | ||
| 133 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 134 | { | ||
| 135 | #[cfg(feature = "log")] | ||
| 136 | ::log::info!($s $(, $x)*); | ||
| 137 | #[cfg(feature = "defmt")] | ||
| 138 | ::defmt::info!($s $(, $x)*); | ||
| 139 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 140 | let _ = ($( & $x ),*); | ||
| 141 | } | ||
| 142 | }; | ||
| 143 | } | ||
| 144 | |||
| 145 | macro_rules! warn { | ||
| 146 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 147 | { | ||
| 148 | #[cfg(feature = "log")] | ||
| 149 | ::log::warn!($s $(, $x)*); | ||
| 150 | #[cfg(feature = "defmt")] | ||
| 151 | ::defmt::warn!($s $(, $x)*); | ||
| 152 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 153 | let _ = ($( & $x ),*); | ||
| 154 | } | ||
| 155 | }; | ||
| 156 | } | ||
| 157 | |||
| 158 | macro_rules! error { | ||
| 159 | ($s:literal $(, $x:expr)* $(,)?) => { | ||
| 160 | { | ||
| 161 | #[cfg(feature = "log")] | ||
| 162 | ::log::error!($s $(, $x)*); | ||
| 163 | #[cfg(feature = "defmt")] | ||
| 164 | ::defmt::error!($s $(, $x)*); | ||
| 165 | #[cfg(not(any(feature = "log", feature="defmt")))] | ||
| 166 | let _ = ($( & $x ),*); | ||
| 167 | } | ||
| 168 | }; | ||
| 169 | } | ||
| 170 | |||
| 171 | #[cfg(feature = "defmt")] | ||
| 172 | macro_rules! unwrap { | ||
| 173 | ($($x:tt)*) => { | ||
| 174 | ::defmt::unwrap!($($x)*) | ||
| 175 | }; | ||
| 176 | } | ||
| 177 | |||
| 178 | #[cfg(not(feature = "defmt"))] | ||
| 179 | macro_rules! unwrap { | ||
| 180 | ($arg:expr) => { | ||
| 181 | match $crate::fmt::Try::into_result($arg) { | ||
| 182 | ::core::result::Result::Ok(t) => t, | ||
| 183 | ::core::result::Result::Err(e) => { | ||
| 184 | ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); | ||
| 185 | } | ||
| 186 | } | ||
| 187 | }; | ||
| 188 | ($arg:expr, $($msg:expr),+ $(,)? ) => { | ||
| 189 | match $crate::fmt::Try::into_result($arg) { | ||
| 190 | ::core::result::Result::Ok(t) => t, | ||
| 191 | ::core::result::Result::Err(e) => { | ||
| 192 | ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); | ||
| 193 | } | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||
| 199 | pub struct NoneError; | ||
| 200 | |||
| 201 | pub trait Try { | ||
| 202 | type Ok; | ||
| 203 | type Error; | ||
| 204 | fn into_result(self) -> Result<Self::Ok, Self::Error>; | ||
| 205 | } | ||
| 206 | |||
| 207 | impl<T> Try for Option<T> { | ||
| 208 | type Ok = T; | ||
| 209 | type Error = NoneError; | ||
| 210 | |||
| 211 | #[inline] | ||
| 212 | fn into_result(self) -> Result<T, NoneError> { | ||
| 213 | self.ok_or(NoneError) | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | impl<T, E> Try for Result<T, E> { | ||
| 218 | type Ok = T; | ||
| 219 | type Error = E; | ||
| 220 | |||
| 221 | #[inline] | ||
| 222 | fn into_result(self) -> Self { | ||
| 223 | self | ||
| 224 | } | ||
| 225 | } | ||
diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs new file mode 100644 index 000000000..c37b67dc4 --- /dev/null +++ b/embassy-stm32-wpan/src/lib.rs | |||
| @@ -0,0 +1,266 @@ | |||
| 1 | #![no_std] | ||
| 2 | |||
| 3 | // This must go FIRST so that all the other modules see its macros. | ||
| 4 | pub mod fmt; | ||
| 5 | |||
| 6 | use core::mem::MaybeUninit; | ||
| 7 | |||
| 8 | use cmd::CmdPacket; | ||
| 9 | use embassy_futures::block_on; | ||
| 10 | use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; | ||
| 11 | use embassy_stm32::interrupt; | ||
| 12 | use embassy_stm32::interrupt::typelevel::Interrupt; | ||
| 13 | use embassy_stm32::ipcc::{Config, Ipcc}; | ||
| 14 | use embassy_stm32::peripherals::IPCC; | ||
| 15 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 16 | use embassy_sync::channel::Channel; | ||
| 17 | use embassy_sync::signal::Signal; | ||
| 18 | use evt::{CcEvt, EvtBox}; | ||
| 19 | use tables::{ | ||
| 20 | BleTable, DeviceInfoTable, Mac802_15_4Table, MemManagerTable, RefTable, SysTable, ThreadTable, TracesTable, | ||
| 21 | WirelessFwInfoTable, | ||
| 22 | }; | ||
| 23 | use unsafe_linked_list::LinkedListNode; | ||
| 24 | |||
| 25 | pub mod ble; | ||
| 26 | pub mod channels; | ||
| 27 | pub mod cmd; | ||
| 28 | pub mod consts; | ||
| 29 | pub mod evt; | ||
| 30 | pub mod mm; | ||
| 31 | pub mod rc; | ||
| 32 | pub mod shci; | ||
| 33 | pub mod sys; | ||
| 34 | pub mod tables; | ||
| 35 | pub mod unsafe_linked_list; | ||
| 36 | |||
| 37 | /// Interrupt handler. | ||
| 38 | pub struct ReceiveInterruptHandler {} | ||
| 39 | |||
| 40 | impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_RX> for ReceiveInterruptHandler { | ||
| 41 | unsafe fn on_interrupt() { | ||
| 42 | if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { | ||
| 43 | debug!("RX SYS evt"); | ||
| 44 | sys::Sys::evt_handler(); | ||
| 45 | } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) { | ||
| 46 | debug!("RX BLE evt"); | ||
| 47 | ble::Ble::evt_handler(); | ||
| 48 | } | ||
| 49 | |||
| 50 | STATE.signal(()); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | pub struct TransmitInterruptHandler {} | ||
| 55 | |||
| 56 | impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_TX> for TransmitInterruptHandler { | ||
| 57 | unsafe fn on_interrupt() { | ||
| 58 | if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { | ||
| 59 | debug!("TX SYS cmd rsp"); | ||
| 60 | let cc = sys::Sys::cmd_evt_handler(); | ||
| 61 | |||
| 62 | LAST_CC_EVT.signal(cc); | ||
| 63 | } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) { | ||
| 64 | debug!("TX MM release"); | ||
| 65 | mm::MemoryManager::free_buf_handler(); | ||
| 66 | } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_HCI_ACL_DATA_CHANNEL) { | ||
| 67 | debug!("TX HCI acl"); | ||
| 68 | ble::Ble::acl_data_handler(); | ||
| 69 | } | ||
| 70 | |||
| 71 | STATE.signal(()); | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | #[link_section = "TL_REF_TABLE"] | ||
| 76 | pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit(); | ||
| 77 | |||
| 78 | #[link_section = "MB_MEM1"] | ||
| 79 | static mut TL_DEVICE_INFO_TABLE: MaybeUninit<DeviceInfoTable> = MaybeUninit::uninit(); | ||
| 80 | |||
| 81 | #[link_section = "MB_MEM1"] | ||
| 82 | static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit(); | ||
| 83 | |||
| 84 | #[link_section = "MB_MEM1"] | ||
| 85 | static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit(); | ||
| 86 | |||
| 87 | #[link_section = "MB_MEM1"] | ||
| 88 | static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit(); | ||
| 89 | |||
| 90 | #[link_section = "MB_MEM1"] | ||
| 91 | static mut TL_MEM_MANAGER_TABLE: MaybeUninit<MemManagerTable> = MaybeUninit::uninit(); | ||
| 92 | |||
| 93 | #[link_section = "MB_MEM1"] | ||
| 94 | static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit(); | ||
| 95 | |||
| 96 | #[link_section = "MB_MEM1"] | ||
| 97 | static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit(); | ||
| 98 | |||
| 99 | #[link_section = "MB_MEM2"] | ||
| 100 | static mut FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 101 | |||
| 102 | // Not in shared RAM | ||
| 103 | static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 104 | |||
| 105 | #[allow(dead_code)] // Not used currently but reserved | ||
| 106 | #[link_section = "MB_MEM2"] | ||
| 107 | static mut TRACES_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 108 | |||
| 109 | type PacketHeader = LinkedListNode; | ||
| 110 | |||
| 111 | const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::<PacketHeader>(); | ||
| 112 | const TL_EVT_HEADER_SIZE: usize = 3; | ||
| 113 | const TL_CS_EVT_SIZE: usize = core::mem::size_of::<evt::CsEvt>(); | ||
| 114 | |||
| 115 | #[link_section = "MB_MEM2"] | ||
| 116 | static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> = | ||
| 117 | MaybeUninit::uninit(); | ||
| 118 | |||
| 119 | #[link_section = "MB_MEM2"] | ||
| 120 | static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 121 | |||
| 122 | #[link_section = "MB_MEM2"] | ||
| 123 | static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 124 | |||
| 125 | #[link_section = "MB_MEM2"] | ||
| 126 | pub static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); | ||
| 127 | |||
| 128 | /** | ||
| 129 | * Queue length of BLE Event | ||
| 130 | * This parameter defines the number of asynchronous events that can be stored in the HCI layer before | ||
| 131 | * being reported to the application. When a command is sent to the BLE core coprocessor, the HCI layer | ||
| 132 | * is waiting for the event with the Num_HCI_Command_Packets set to 1. The receive queue shall be large | ||
| 133 | * enough to store all asynchronous events received in between. | ||
| 134 | * When CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE is set to 27, this allow to store three 255 bytes long asynchronous events | ||
| 135 | * between the HCI command and its event. | ||
| 136 | * This parameter depends on the value given to CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE. When the queue size is to small, | ||
| 137 | * the system may hang if the queue is full with asynchronous events and the HCI layer is still waiting | ||
| 138 | * for a CC/CS event, In that case, the notification TL_BLE_HCI_ToNot() is called to indicate | ||
| 139 | * to the application a HCI command did not receive its command event within 30s (Default HCI Timeout). | ||
| 140 | */ | ||
| 141 | const CFG_TLBLE_EVT_QUEUE_LENGTH: usize = 5; | ||
| 142 | const CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255; | ||
| 143 | const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE; | ||
| 144 | |||
| 145 | const fn divc(x: usize, y: usize) -> usize { | ||
| 146 | ((x) + (y) - 1) / (y) | ||
| 147 | } | ||
| 148 | |||
| 149 | const POOL_SIZE: usize = CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); | ||
| 150 | |||
| 151 | #[link_section = "MB_MEM2"] | ||
| 152 | static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit(); | ||
| 153 | |||
| 154 | #[link_section = "MB_MEM2"] | ||
| 155 | static mut SYS_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> = | ||
| 156 | MaybeUninit::uninit(); | ||
| 157 | |||
| 158 | #[link_section = "MB_MEM2"] | ||
| 159 | static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> = | ||
| 160 | MaybeUninit::uninit(); | ||
| 161 | |||
| 162 | #[link_section = "MB_MEM2"] | ||
| 163 | static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); | ||
| 164 | |||
| 165 | #[link_section = "MB_MEM2"] | ||
| 166 | // fuck these "magic" numbers from ST ---v---v | ||
| 167 | static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); | ||
| 168 | |||
| 169 | /// current event that is produced during IPCC IRQ handler execution | ||
| 170 | /// on SYS channel | ||
| 171 | static EVT_CHANNEL: Channel<CriticalSectionRawMutex, EvtBox, 32> = Channel::new(); | ||
| 172 | |||
| 173 | /// last received Command Complete event | ||
| 174 | static LAST_CC_EVT: Signal<CriticalSectionRawMutex, CcEvt> = Signal::new(); | ||
| 175 | |||
| 176 | static STATE: Signal<CriticalSectionRawMutex, ()> = Signal::new(); | ||
| 177 | |||
| 178 | pub struct TlMbox<'d> { | ||
| 179 | _ipcc: PeripheralRef<'d, IPCC>, | ||
| 180 | } | ||
| 181 | |||
| 182 | impl<'d> TlMbox<'d> { | ||
| 183 | pub fn init( | ||
| 184 | ipcc: impl Peripheral<P = IPCC> + 'd, | ||
| 185 | _irqs: impl interrupt::typelevel::Binding<interrupt::typelevel::IPCC_C1_RX, ReceiveInterruptHandler> | ||
| 186 | + interrupt::typelevel::Binding<interrupt::typelevel::IPCC_C1_TX, TransmitInterruptHandler>, | ||
| 187 | config: Config, | ||
| 188 | ) -> Self { | ||
| 189 | into_ref!(ipcc); | ||
| 190 | |||
| 191 | unsafe { | ||
| 192 | TL_REF_TABLE = MaybeUninit::new(RefTable { | ||
| 193 | device_info_table: TL_DEVICE_INFO_TABLE.as_mut_ptr(), | ||
| 194 | ble_table: TL_BLE_TABLE.as_ptr(), | ||
| 195 | thread_table: TL_THREAD_TABLE.as_ptr(), | ||
| 196 | sys_table: TL_SYS_TABLE.as_ptr(), | ||
| 197 | mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), | ||
| 198 | traces_table: TL_TRACES_TABLE.as_ptr(), | ||
| 199 | mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), | ||
| 200 | }); | ||
| 201 | |||
| 202 | TL_SYS_TABLE = MaybeUninit::zeroed(); | ||
| 203 | TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed(); | ||
| 204 | TL_BLE_TABLE = MaybeUninit::zeroed(); | ||
| 205 | TL_THREAD_TABLE = MaybeUninit::zeroed(); | ||
| 206 | TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed(); | ||
| 207 | TL_TRACES_TABLE = MaybeUninit::zeroed(); | ||
| 208 | TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed(); | ||
| 209 | |||
| 210 | EVT_POOL = MaybeUninit::zeroed(); | ||
| 211 | SYS_SPARE_EVT_BUF = MaybeUninit::zeroed(); | ||
| 212 | BLE_SPARE_EVT_BUF = MaybeUninit::zeroed(); | ||
| 213 | |||
| 214 | CS_BUFFER = MaybeUninit::zeroed(); | ||
| 215 | BLE_CMD_BUFFER = MaybeUninit::zeroed(); | ||
| 216 | HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed(); | ||
| 217 | } | ||
| 218 | |||
| 219 | Ipcc::enable(config); | ||
| 220 | |||
| 221 | sys::Sys::enable(); | ||
| 222 | ble::Ble::enable(); | ||
| 223 | mm::MemoryManager::enable(); | ||
| 224 | |||
| 225 | // enable interrupts | ||
| 226 | interrupt::typelevel::IPCC_C1_RX::unpend(); | ||
| 227 | interrupt::typelevel::IPCC_C1_TX::unpend(); | ||
| 228 | |||
| 229 | unsafe { interrupt::typelevel::IPCC_C1_RX::enable() }; | ||
| 230 | unsafe { interrupt::typelevel::IPCC_C1_TX::enable() }; | ||
| 231 | |||
| 232 | STATE.reset(); | ||
| 233 | |||
| 234 | Self { _ipcc: ipcc } | ||
| 235 | } | ||
| 236 | |||
| 237 | /// Returns CPU2 wireless firmware information (if present). | ||
| 238 | pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> { | ||
| 239 | let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table }; | ||
| 240 | |||
| 241 | // Zero version indicates that CPU2 wasn't active and didn't fill the information table | ||
| 242 | if info.version != 0 { | ||
| 243 | Some(*info) | ||
| 244 | } else { | ||
| 245 | None | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | /// picks single [`EvtBox`] from internal event queue. | ||
| 250 | /// | ||
| 251 | /// Internal event queu is populated in IPCC_RX_IRQ handler | ||
| 252 | pub fn dequeue_event(&mut self) -> Option<EvtBox> { | ||
| 253 | EVT_CHANNEL.try_recv().ok() | ||
| 254 | } | ||
| 255 | |||
| 256 | /// retrieves last Command Complete event and removes it from mailbox | ||
| 257 | pub fn pop_last_cc_evt(&mut self) -> Option<CcEvt> { | ||
| 258 | if LAST_CC_EVT.signaled() { | ||
| 259 | let cc = block_on(LAST_CC_EVT.wait()); | ||
| 260 | LAST_CC_EVT.reset(); | ||
| 261 | Some(cc) | ||
| 262 | } else { | ||
| 263 | None | ||
| 264 | } | ||
| 265 | } | ||
| 266 | } | ||
diff --git a/embassy-stm32-wpan/src/mm.rs b/embassy-stm32-wpan/src/mm.rs new file mode 100644 index 000000000..ed13b0dbf --- /dev/null +++ b/embassy-stm32-wpan/src/mm.rs | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | //! Memory manager routines | ||
| 2 | |||
| 3 | use core::mem::MaybeUninit; | ||
| 4 | |||
| 5 | use embassy_stm32::ipcc::Ipcc; | ||
| 6 | |||
| 7 | use crate::evt::EvtPacket; | ||
| 8 | use crate::tables::MemManagerTable; | ||
| 9 | use crate::unsafe_linked_list::LinkedListNode; | ||
| 10 | use crate::{ | ||
| 11 | channels, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF, | ||
| 12 | TL_MEM_MANAGER_TABLE, TL_REF_TABLE, | ||
| 13 | }; | ||
| 14 | |||
| 15 | pub(super) struct MemoryManager; | ||
| 16 | |||
| 17 | impl MemoryManager { | ||
| 18 | pub fn enable() { | ||
| 19 | unsafe { | ||
| 20 | LinkedListNode::init_head(FREE_BUF_QUEUE.as_mut_ptr()); | ||
| 21 | LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); | ||
| 22 | |||
| 23 | TL_MEM_MANAGER_TABLE = MaybeUninit::new(MemManagerTable { | ||
| 24 | spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), | ||
| 25 | spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), | ||
| 26 | blepool: EVT_POOL.as_ptr().cast(), | ||
| 27 | blepoolsize: POOL_SIZE as u32, | ||
| 28 | pevt_free_buffer_queue: FREE_BUF_QUEUE.as_mut_ptr(), | ||
| 29 | traces_evt_pool: core::ptr::null(), | ||
| 30 | tracespoolsize: 0, | ||
| 31 | }); | ||
| 32 | } | ||
| 33 | } | ||
| 34 | |||
| 35 | pub fn evt_drop(evt: *mut EvtPacket) { | ||
| 36 | unsafe { | ||
| 37 | let list_node = evt.cast(); | ||
| 38 | |||
| 39 | LinkedListNode::insert_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); | ||
| 40 | |||
| 41 | let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); | ||
| 42 | |||
| 43 | // postpone event buffer freeing to IPCC interrupt handler | ||
| 44 | if channel_is_busy { | ||
| 45 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); | ||
| 46 | } else { | ||
| 47 | Self::send_free_buf(); | ||
| 48 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | } | ||
| 52 | |||
| 53 | /// gives free event buffers back to CPU2 from local buffer queue | ||
| 54 | pub fn send_free_buf() { | ||
| 55 | unsafe { | ||
| 56 | let mut node_ptr = core::ptr::null_mut(); | ||
| 57 | let node_ptr_ptr: *mut _ = &mut node_ptr; | ||
| 58 | |||
| 59 | while !LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { | ||
| 60 | LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), node_ptr_ptr); | ||
| 61 | LinkedListNode::insert_tail( | ||
| 62 | (*(*TL_REF_TABLE.as_ptr()).mem_manager_table).pevt_free_buffer_queue, | ||
| 63 | node_ptr, | ||
| 64 | ); | ||
| 65 | } | ||
| 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 | } | ||
| 75 | } | ||
diff --git a/embassy-stm32-wpan/src/rc.rs b/embassy-stm32-wpan/src/rc.rs new file mode 100644 index 000000000..aae2265ed --- /dev/null +++ b/embassy-stm32-wpan/src/rc.rs | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | use crate::ble::Ble; | ||
| 2 | use crate::consts::TlPacketType; | ||
| 3 | use crate::{shci, TlMbox, STATE}; | ||
| 4 | |||
| 5 | pub struct RadioCoprocessor<'d> { | ||
| 6 | mbox: TlMbox<'d>, | ||
| 7 | rx_buf: [u8; 500], | ||
| 8 | } | ||
| 9 | |||
| 10 | impl<'d> RadioCoprocessor<'d> { | ||
| 11 | pub fn new(mbox: TlMbox<'d>) -> Self { | ||
| 12 | Self { | ||
| 13 | mbox, | ||
| 14 | rx_buf: [0u8; 500], | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | pub fn write(&self, buf: &[u8]) { | ||
| 19 | let cmd_code = buf[0]; | ||
| 20 | let cmd = TlPacketType::try_from(cmd_code).unwrap(); | ||
| 21 | |||
| 22 | match &cmd { | ||
| 23 | TlPacketType::BleCmd => Ble::ble_send_cmd(buf), | ||
| 24 | _ => todo!(), | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | pub async fn read(&mut self) -> &[u8] { | ||
| 29 | loop { | ||
| 30 | STATE.wait().await; | ||
| 31 | |||
| 32 | while let Some(evt) = self.mbox.dequeue_event() { | ||
| 33 | let event = evt.evt(); | ||
| 34 | |||
| 35 | evt.write(&mut self.rx_buf).unwrap(); | ||
| 36 | |||
| 37 | if event.kind() == 18 { | ||
| 38 | shci::shci_ble_init(Default::default()); | ||
| 39 | self.rx_buf[0] = 0x04; | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | if self.mbox.pop_last_cc_evt().is_some() { | ||
| 44 | continue; | ||
| 45 | } | ||
| 46 | |||
| 47 | return &self.rx_buf; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | } | ||
diff --git a/embassy-stm32/src/tl_mbox/shci.rs b/embassy-stm32-wpan/src/shci.rs index 6b5b2dd19..8537995ff 100644 --- a/embassy-stm32/src/tl_mbox/shci.rs +++ b/embassy-stm32-wpan/src/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!("sending SHCI"); | ||
| 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 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::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-wpan/src/sys.rs index 9685fb920..a19d12d27 100644 --- a/embassy-stm32/src/tl_mbox/sys.rs +++ b/embassy-stm32-wpan/src/sys.rs | |||
| @@ -1,11 +1,12 @@ | |||
| 1 | use embassy_futures::block_on; | 1 | use core::mem::MaybeUninit; |
| 2 | 2 | ||
| 3 | use super::cmd::{CmdPacket, CmdSerial}; | 3 | use embassy_stm32::ipcc::Ipcc; |
| 4 | use super::consts::TlPacketType; | 4 | |
| 5 | use super::evt::{CcEvt, EvtBox, EvtSerial}; | 5 | use crate::cmd::{CmdPacket, CmdSerial}; |
| 6 | use super::unsafe_linked_list::LinkedListNode; | 6 | use crate::evt::{CcEvt, EvtBox, EvtSerial}; |
| 7 | use super::{channels, SysTable, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_CHANNEL, TL_REF_TABLE, TL_SYS_TABLE}; | 7 | use crate::tables::SysTable; |
| 8 | use crate::tl_mbox::ipcc::Ipcc; | 8 | use crate::unsafe_linked_list::LinkedListNode; |
| 9 | use crate::{channels, EVT_CHANNEL, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE}; | ||
| 9 | 10 | ||
| 10 | pub struct Sys; | 11 | pub struct Sys; |
| 11 | 12 | ||
| @@ -14,34 +15,15 @@ impl Sys { | |||
| 14 | unsafe { | 15 | unsafe { |
| 15 | LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); | 16 | LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); |
| 16 | 17 | ||
| 17 | TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable { | 18 | TL_SYS_TABLE = MaybeUninit::new(SysTable { |
| 18 | pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), | 19 | pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), |
| 19 | sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), | 20 | sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), |
| 20 | }); | 21 | }) |
| 21 | } | 22 | } |
| 22 | 23 | ||
| 23 | Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true); | 24 | Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true); |
| 24 | } | 25 | } |
| 25 | 26 | ||
| 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 | |||
| 42 | Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); | ||
| 43 | } | ||
| 44 | |||
| 45 | pub fn cmd_evt_handler() -> CcEvt { | 27 | pub fn cmd_evt_handler() -> CcEvt { |
| 46 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, false); | 28 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, false); |
| 47 | 29 | ||
| @@ -55,29 +37,34 @@ 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 | let cmd_serial: *const CmdSerial = &(*pcmd).cmdserial; |
| 60 | let evt_serial: *const EvtSerial = cmd_serial.cast(); | 42 | let evt_serial: *const EvtSerial = cmd_serial.cast(); |
| 61 | let cc = (*evt_serial).evt.payload.as_ptr().cast(); | 43 | let cc: *const CcEvt = (*evt_serial).evt.payload.as_ptr().cast(); |
| 62 | *cc | 44 | *cc |
| 63 | } | 45 | } |
| 64 | } | 46 | } |
| 65 | 47 | ||
| 66 | #[allow(dead_code)] | 48 | pub fn evt_handler() { |
| 67 | pub fn send_cmd(buf: &[u8]) { | ||
| 68 | unsafe { | 49 | unsafe { |
| 69 | // TODO: check this | 50 | let mut node_ptr = core::ptr::null_mut(); |
| 70 | let cmd_buffer = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer; | 51 | 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 | 52 | ||
| 74 | core::ptr::copy(buf.as_ptr(), cmd_serial_buf, buf.len()); | 53 | while !LinkedListNode::is_empty(SYSTEM_EVT_QUEUE.as_mut_ptr()) { |
| 54 | LinkedListNode::remove_head(SYSTEM_EVT_QUEUE.as_mut_ptr(), node_ptr_ptr); | ||
| 75 | 55 | ||
| 76 | let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer; | 56 | let event = node_ptr.cast(); |
| 77 | cmd_packet.cmd_serial.ty = TlPacketType::SysCmd as u8; | 57 | let event = EvtBox::new(event); |
| 78 | 58 | ||
| 79 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); | 59 | EVT_CHANNEL.try_send(event).unwrap(); |
| 80 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); | 60 | } |
| 81 | } | 61 | } |
| 62 | |||
| 63 | Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); | ||
| 64 | } | ||
| 65 | |||
| 66 | pub fn send_cmd() { | ||
| 67 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); | ||
| 68 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); | ||
| 82 | } | 69 | } |
| 83 | } | 70 | } |
diff --git a/embassy-stm32-wpan/src/tables.rs b/embassy-stm32-wpan/src/tables.rs new file mode 100644 index 000000000..151216958 --- /dev/null +++ b/embassy-stm32-wpan/src/tables.rs | |||
| @@ -0,0 +1,175 @@ | |||
| 1 | use bit_field::BitField; | ||
| 2 | |||
| 3 | use crate::cmd::{AclDataPacket, CmdPacket}; | ||
| 4 | use crate::unsafe_linked_list::LinkedListNode; | ||
| 5 | |||
| 6 | #[derive(Debug, Copy, Clone)] | ||
| 7 | #[repr(C, packed)] | ||
| 8 | pub struct SafeBootInfoTable { | ||
| 9 | version: u32, | ||
| 10 | } | ||
| 11 | |||
| 12 | #[derive(Debug, Copy, Clone)] | ||
| 13 | #[repr(C, packed)] | ||
| 14 | pub struct RssInfoTable { | ||
| 15 | pub version: u32, | ||
| 16 | pub memory_size: u32, | ||
| 17 | pub rss_info: u32, | ||
| 18 | } | ||
| 19 | |||
| 20 | /** | ||
| 21 | * Version | ||
| 22 | * [0:3] = Build - 0: Untracked - 15:Released - x: Tracked version | ||
| 23 | * [4:7] = branch - 0: Mass Market - x: ... | ||
| 24 | * [8:15] = Subversion | ||
| 25 | * [16:23] = Version minor | ||
| 26 | * [24:31] = Version major | ||
| 27 | * | ||
| 28 | * Memory Size | ||
| 29 | * [0:7] = Flash ( Number of 4k sector) | ||
| 30 | * [8:15] = Reserved ( Shall be set to 0 - may be used as flash extension ) | ||
| 31 | * [16:23] = SRAM2b ( Number of 1k sector) | ||
| 32 | * [24:31] = SRAM2a ( Number of 1k sector) | ||
| 33 | */ | ||
| 34 | #[derive(Debug, Copy, Clone)] | ||
| 35 | #[repr(C, packed)] | ||
| 36 | pub struct WirelessFwInfoTable { | ||
| 37 | pub version: u32, | ||
| 38 | pub memory_size: u32, | ||
| 39 | pub thread_info: u32, | ||
| 40 | pub ble_info: u32, | ||
| 41 | } | ||
| 42 | |||
| 43 | impl WirelessFwInfoTable { | ||
| 44 | pub fn version_major(&self) -> u8 { | ||
| 45 | let version = self.version; | ||
| 46 | (version.get_bits(24..31) & 0xff) as u8 | ||
| 47 | } | ||
| 48 | |||
| 49 | pub fn version_minor(&self) -> u8 { | ||
| 50 | let version = self.version; | ||
| 51 | (version.clone().get_bits(16..23) & 0xff) as u8 | ||
| 52 | } | ||
| 53 | |||
| 54 | pub fn subversion(&self) -> u8 { | ||
| 55 | let version = self.version; | ||
| 56 | (version.clone().get_bits(8..15) & 0xff) as u8 | ||
| 57 | } | ||
| 58 | |||
| 59 | /// Size of FLASH, expressed in number of 4K sectors. | ||
| 60 | pub fn flash_size(&self) -> u8 { | ||
| 61 | let memory_size = self.memory_size; | ||
| 62 | (memory_size.clone().get_bits(0..7) & 0xff) as u8 | ||
| 63 | } | ||
| 64 | |||
| 65 | /// Size of SRAM2a, expressed in number of 1K sectors. | ||
| 66 | pub fn sram2a_size(&self) -> u8 { | ||
| 67 | let memory_size = self.memory_size; | ||
| 68 | (memory_size.clone().get_bits(24..31) & 0xff) as u8 | ||
| 69 | } | ||
| 70 | |||
| 71 | /// Size of SRAM2b, expressed in number of 1K sectors. | ||
| 72 | pub fn sram2b_size(&self) -> u8 { | ||
| 73 | let memory_size = self.memory_size; | ||
| 74 | (memory_size.clone().get_bits(16..23) & 0xff) as u8 | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | #[derive(Debug, Clone)] | ||
| 79 | #[repr(C, align(4))] | ||
| 80 | pub struct DeviceInfoTable { | ||
| 81 | pub safe_boot_info_table: SafeBootInfoTable, | ||
| 82 | pub rss_info_table: RssInfoTable, | ||
| 83 | pub wireless_fw_info_table: WirelessFwInfoTable, | ||
| 84 | } | ||
| 85 | |||
| 86 | #[derive(Debug)] | ||
| 87 | #[repr(C, align(4))] | ||
| 88 | pub struct BleTable { | ||
| 89 | pub pcmd_buffer: *mut CmdPacket, | ||
| 90 | pub pcs_buffer: *const u8, | ||
| 91 | pub pevt_queue: *const u8, | ||
| 92 | pub phci_acl_data_buffer: *mut AclDataPacket, | ||
| 93 | } | ||
| 94 | |||
| 95 | #[derive(Debug)] | ||
| 96 | #[repr(C, align(4))] | ||
| 97 | pub struct ThreadTable { | ||
| 98 | pub nostack_buffer: *const u8, | ||
| 99 | pub clicmdrsp_buffer: *const u8, | ||
| 100 | pub otcmdrsp_buffer: *const u8, | ||
| 101 | } | ||
| 102 | |||
| 103 | // TODO: use later | ||
| 104 | #[derive(Debug)] | ||
| 105 | #[repr(C, align(4))] | ||
| 106 | pub struct LldTestsTable { | ||
| 107 | pub clicmdrsp_buffer: *const u8, | ||
| 108 | pub m0cmd_buffer: *const u8, | ||
| 109 | } | ||
| 110 | |||
| 111 | // TODO: use later | ||
| 112 | #[derive(Debug)] | ||
| 113 | #[repr(C, align(4))] | ||
| 114 | pub struct BleLldTable { | ||
| 115 | pub cmdrsp_buffer: *const u8, | ||
| 116 | pub m0cmd_buffer: *const u8, | ||
| 117 | } | ||
| 118 | |||
| 119 | // TODO: use later | ||
| 120 | #[derive(Debug)] | ||
| 121 | #[repr(C, align(4))] | ||
| 122 | pub struct ZigbeeTable { | ||
| 123 | pub notif_m0_to_m4_buffer: *const u8, | ||
| 124 | pub appli_cmd_m4_to_m0_bufer: *const u8, | ||
| 125 | pub request_m0_to_m4_buffer: *const u8, | ||
| 126 | } | ||
| 127 | |||
| 128 | #[derive(Debug)] | ||
| 129 | #[repr(C, align(4))] | ||
| 130 | pub struct SysTable { | ||
| 131 | pub pcmd_buffer: *mut CmdPacket, | ||
| 132 | pub sys_queue: *const LinkedListNode, | ||
| 133 | } | ||
| 134 | |||
| 135 | #[derive(Debug)] | ||
| 136 | #[repr(C, align(4))] | ||
| 137 | pub struct MemManagerTable { | ||
| 138 | pub spare_ble_buffer: *const u8, | ||
| 139 | pub spare_sys_buffer: *const u8, | ||
| 140 | |||
| 141 | pub blepool: *const u8, | ||
| 142 | pub blepoolsize: u32, | ||
| 143 | |||
| 144 | pub pevt_free_buffer_queue: *mut LinkedListNode, | ||
| 145 | |||
| 146 | pub traces_evt_pool: *const u8, | ||
| 147 | pub tracespoolsize: u32, | ||
| 148 | } | ||
| 149 | |||
| 150 | #[derive(Debug)] | ||
| 151 | #[repr(C, align(4))] | ||
| 152 | pub struct TracesTable { | ||
| 153 | pub traces_queue: *const u8, | ||
| 154 | } | ||
| 155 | |||
| 156 | #[derive(Debug)] | ||
| 157 | #[repr(C, align(4))] | ||
| 158 | pub struct Mac802_15_4Table { | ||
| 159 | pub p_cmdrsp_buffer: *const u8, | ||
| 160 | pub p_notack_buffer: *const u8, | ||
| 161 | pub evt_queue: *const u8, | ||
| 162 | } | ||
| 163 | |||
| 164 | /// Reference table. Contains pointers to all other tables. | ||
| 165 | #[derive(Debug, Copy, Clone)] | ||
| 166 | #[repr(C)] | ||
| 167 | pub struct RefTable { | ||
| 168 | pub device_info_table: *const DeviceInfoTable, | ||
| 169 | pub ble_table: *const BleTable, | ||
| 170 | pub thread_table: *const ThreadTable, | ||
| 171 | pub sys_table: *const SysTable, | ||
| 172 | pub mem_manager_table: *const MemManagerTable, | ||
| 173 | pub traces_table: *const TracesTable, | ||
| 174 | pub mac_802_15_4_table: *const Mac802_15_4Table, | ||
| 175 | } | ||
diff --git a/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs b/embassy-stm32-wpan/src/unsafe_linked_list.rs index 482e2bf5a..52c106fa2 100644 --- a/embassy-stm32/src/tl_mbox/unsafe_linked_list.rs +++ b/embassy-stm32-wpan/src/unsafe_linked_list.rs | |||
| @@ -57,6 +57,7 @@ impl LinkedListNode { | |||
| 57 | }); | 57 | }); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | /// Remove `node` from the linked list | ||
| 60 | pub unsafe fn remove_node(mut node: *mut LinkedListNode) { | 61 | pub unsafe fn remove_node(mut node: *mut LinkedListNode) { |
| 61 | interrupt::free(|_| { | 62 | interrupt::free(|_| { |
| 62 | (*(*node).prev).next = (*node).next; | 63 | (*(*node).prev).next = (*node).next; |
| @@ -64,6 +65,7 @@ impl LinkedListNode { | |||
| 64 | }); | 65 | }); |
| 65 | } | 66 | } |
| 66 | 67 | ||
| 68 | /// Remove `list_head` into `node` | ||
| 67 | pub unsafe fn remove_head(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { | 69 | pub unsafe fn remove_head(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { |
| 68 | interrupt::free(|_| { | 70 | interrupt::free(|_| { |
| 69 | *node = (*list_head).next; | 71 | *node = (*list_head).next; |
| @@ -71,10 +73,11 @@ impl LinkedListNode { | |||
| 71 | }); | 73 | }); |
| 72 | } | 74 | } |
| 73 | 75 | ||
| 74 | pub unsafe fn remove_tail(mut list_head: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { | 76 | /// Remove `list_tail` into `node` |
| 77 | pub unsafe fn remove_tail(mut list_tail: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) { | ||
| 75 | interrupt::free(|_| { | 78 | interrupt::free(|_| { |
| 76 | *node = (*list_head).prev; | 79 | *node = (*list_tail).prev; |
| 77 | Self::remove_node((*list_head).prev); | 80 | Self::remove_node((*list_tail).prev); |
| 78 | }); | 81 | }); |
| 79 | } | 82 | } |
| 80 | 83 | ||
diff --git a/embassy-stm32/src/tl_mbox/ipcc.rs b/embassy-stm32/src/ipcc.rs index d1ac731ed..8bb0774b8 100644 --- a/embassy-stm32/src/tl_mbox/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs | |||
| @@ -167,8 +167,68 @@ impl sealed::Instance for crate::peripherals::IPCC { | |||
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | unsafe fn _configure_pwr() { | 169 | unsafe fn _configure_pwr() { |
| 170 | let pwr = crate::pac::PWR; | ||
| 170 | let rcc = crate::pac::RCC; | 171 | let rcc = crate::pac::RCC; |
| 171 | 172 | ||
| 173 | rcc.cfgr().modify(|w| w.set_stopwuck(true)); | ||
| 174 | |||
| 175 | pwr.cr1().modify(|w| w.set_dbp(true)); | ||
| 176 | pwr.cr1().modify(|w| w.set_dbp(true)); | ||
| 177 | |||
| 178 | // configure LSE | ||
| 179 | rcc.bdcr().modify(|w| w.set_lseon(true)); | ||
| 180 | |||
| 181 | // select system clock source = PLL | ||
| 182 | // set PLL coefficients | ||
| 183 | // m: 2, | ||
| 184 | // n: 12, | ||
| 185 | // r: 3, | ||
| 186 | // q: 4, | ||
| 187 | // p: 3, | ||
| 188 | let src_bits = 0b11; | ||
| 189 | let pllp = (3 - 1) & 0b11111; | ||
| 190 | let pllq = (4 - 1) & 0b111; | ||
| 191 | let pllr = (3 - 1) & 0b111; | ||
| 192 | let plln = 12 & 0b1111111; | ||
| 193 | let pllm = (2 - 1) & 0b111; | ||
| 194 | rcc.pllcfgr().modify(|w| { | ||
| 195 | w.set_pllsrc(src_bits); | ||
| 196 | w.set_pllm(pllm); | ||
| 197 | w.set_plln(plln); | ||
| 198 | w.set_pllr(pllr); | ||
| 199 | w.set_pllp(pllp); | ||
| 200 | w.set_pllpen(true); | ||
| 201 | w.set_pllq(pllq); | ||
| 202 | w.set_pllqen(true); | ||
| 203 | }); | ||
| 204 | // enable PLL | ||
| 205 | rcc.cr().modify(|w| w.set_pllon(true)); | ||
| 206 | rcc.cr().write(|w| w.set_hsion(false)); | ||
| 207 | // while !rcc.cr().read().pllrdy() {} | ||
| 208 | |||
| 209 | // configure SYSCLK mux to use PLL clocl | ||
| 210 | rcc.cfgr().modify(|w| w.set_sw(0b11)); | ||
| 211 | |||
| 212 | // configure CPU1 & CPU2 dividers | ||
| 213 | rcc.cfgr().modify(|w| w.set_hpre(0)); // not divided | ||
| 214 | rcc.extcfgr().modify(|w| { | ||
| 215 | w.set_c2hpre(0b1000); // div2 | ||
| 216 | w.set_shdhpre(0); // not divided | ||
| 217 | }); | ||
| 218 | |||
| 219 | // apply APB1 / APB2 values | ||
| 220 | rcc.cfgr().modify(|w| { | ||
| 221 | w.set_ppre1(0b000); // not divided | ||
| 222 | w.set_ppre2(0b000); // not divided | ||
| 223 | }); | ||
| 224 | |||
| 225 | // TODO: required | ||
| 172 | // set RF wake-up clock = LSE | 226 | // set RF wake-up clock = LSE |
| 173 | rcc.csr().modify(|w| w.set_rfwkpsel(0b01)); | 227 | rcc.csr().modify(|w| w.set_rfwkpsel(0b01)); |
| 228 | |||
| 229 | // set LPTIM1 & LPTIM2 clock source | ||
| 230 | rcc.ccipr().modify(|w| { | ||
| 231 | w.set_lptim1sel(0b00); // PCLK | ||
| 232 | w.set_lptim2sel(0b00); // PCLK | ||
| 233 | }); | ||
| 174 | } | 234 | } |
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index f4ec0a80d..6fde61c06 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -41,6 +41,8 @@ pub mod crc; | |||
| 41 | pub mod flash; | 41 | pub mod flash; |
| 42 | #[cfg(all(spi_v1, rcc_f4))] | 42 | #[cfg(all(spi_v1, rcc_f4))] |
| 43 | pub mod i2s; | 43 | pub mod i2s; |
| 44 | #[cfg(stm32wb)] | ||
| 45 | pub mod ipcc; | ||
| 44 | pub mod pwm; | 46 | pub mod pwm; |
| 45 | #[cfg(quadspi)] | 47 | #[cfg(quadspi)] |
| 46 | pub mod qspi; | 48 | pub mod qspi; |
| @@ -52,8 +54,6 @@ pub mod rtc; | |||
| 52 | pub mod sdmmc; | 54 | pub mod sdmmc; |
| 53 | #[cfg(spi)] | 55 | #[cfg(spi)] |
| 54 | pub mod spi; | 56 | pub mod spi; |
| 55 | #[cfg(stm32wb)] | ||
| 56 | pub mod tl_mbox; | ||
| 57 | #[cfg(usart)] | 57 | #[cfg(usart)] |
| 58 | pub mod usart; | 58 | pub mod usart; |
| 59 | #[cfg(usb)] | 59 | #[cfg(usb)] |
diff --git a/embassy-stm32/src/tl_mbox/cmd.rs b/embassy-stm32/src/tl_mbox/cmd.rs deleted file mode 100644 index 3507c3231..000000000 --- a/embassy-stm32/src/tl_mbox/cmd.rs +++ /dev/null | |||
| @@ -1,49 +0,0 @@ | |||
| 1 | use super::PacketHeader; | ||
| 2 | |||
| 3 | #[repr(C, packed)] | ||
| 4 | #[derive(Copy, Clone)] | ||
| 5 | pub struct Cmd { | ||
| 6 | pub cmd_code: u16, | ||
| 7 | pub payload_len: u8, | ||
| 8 | pub payload: [u8; 255], | ||
| 9 | } | ||
| 10 | |||
| 11 | impl Default for Cmd { | ||
| 12 | fn default() -> Self { | ||
| 13 | Self { | ||
| 14 | cmd_code: 0, | ||
| 15 | payload_len: 0, | ||
| 16 | payload: [0u8; 255], | ||
| 17 | } | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | #[repr(C, packed)] | ||
| 22 | #[derive(Copy, Clone, Default)] | ||
| 23 | pub struct CmdSerial { | ||
| 24 | pub ty: u8, | ||
| 25 | pub cmd: Cmd, | ||
| 26 | } | ||
| 27 | |||
| 28 | #[repr(C, packed)] | ||
| 29 | #[derive(Copy, Clone, Default)] | ||
| 30 | pub struct CmdPacket { | ||
| 31 | pub header: PacketHeader, | ||
| 32 | pub cmd_serial: CmdSerial, | ||
| 33 | } | ||
| 34 | |||
| 35 | #[repr(C, packed)] | ||
| 36 | #[derive(Copy, Clone)] | ||
| 37 | pub struct AclDataSerial { | ||
| 38 | pub ty: u8, | ||
| 39 | pub handle: u16, | ||
| 40 | pub length: u16, | ||
| 41 | pub acl_data: [u8; 1], | ||
| 42 | } | ||
| 43 | |||
| 44 | #[repr(C, packed)] | ||
| 45 | #[derive(Copy, Clone)] | ||
| 46 | pub struct AclDataPacket { | ||
| 47 | pub header: PacketHeader, | ||
| 48 | pub acl_data_serial: AclDataSerial, | ||
| 49 | } | ||
diff --git a/embassy-stm32/src/tl_mbox/mm.rs b/embassy-stm32/src/tl_mbox/mm.rs deleted file mode 100644 index e28a6aa0c..000000000 --- a/embassy-stm32/src/tl_mbox/mm.rs +++ /dev/null | |||
| @@ -1,67 +0,0 @@ | |||
| 1 | use super::evt::EvtPacket; | ||
| 2 | use super::unsafe_linked_list::LinkedListNode; | ||
| 3 | use super::{ | ||
| 4 | channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUFF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, | ||
| 5 | SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, TL_REF_TABLE, | ||
| 6 | }; | ||
| 7 | use crate::tl_mbox::ipcc::Ipcc; | ||
| 8 | |||
| 9 | pub struct MemoryManager; | ||
| 10 | |||
| 11 | impl MemoryManager { | ||
| 12 | pub fn enable() { | ||
| 13 | unsafe { | ||
| 14 | LinkedListNode::init_head(FREE_BUFF_QUEUE.as_mut_ptr()); | ||
| 15 | LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); | ||
| 16 | |||
| 17 | TL_MEM_MANAGER_TABLE.as_mut_ptr().write_volatile(MemManagerTable { | ||
| 18 | spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), | ||
| 19 | spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(), | ||
| 20 | ble_pool: EVT_POOL.as_ptr().cast(), | ||
| 21 | ble_pool_size: POOL_SIZE as u32, | ||
| 22 | pevt_free_buffer_queue: FREE_BUFF_QUEUE.as_mut_ptr(), | ||
| 23 | traces_evt_pool: core::ptr::null(), | ||
| 24 | traces_pool_size: 0, | ||
| 25 | }); | ||
| 26 | } | ||
| 27 | } | ||
| 28 | |||
| 29 | pub fn evt_handler() { | ||
| 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 | } | ||
| 34 | |||
| 35 | pub fn evt_drop(evt: *mut EvtPacket) { | ||
| 36 | unsafe { | ||
| 37 | let list_node = evt.cast(); | ||
| 38 | |||
| 39 | LinkedListNode::remove_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); | ||
| 40 | } | ||
| 41 | |||
| 42 | let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); | ||
| 43 | |||
| 44 | // postpone event buffer freeing to IPCC interrupt handler | ||
| 45 | if channel_is_busy { | ||
| 46 | Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); | ||
| 47 | } else { | ||
| 48 | Self::send_free_buf(); | ||
| 49 | Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); | ||
| 50 | } | ||
| 51 | } | ||
| 52 | |||
| 53 | fn send_free_buf() { | ||
| 54 | unsafe { | ||
| 55 | let mut node_ptr = core::ptr::null_mut(); | ||
| 56 | let node_ptr_ptr: *mut _ = &mut node_ptr; | ||
| 57 | |||
| 58 | while !LinkedListNode::is_empty(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()) { | ||
| 59 | LinkedListNode::remove_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), node_ptr_ptr); | ||
| 60 | LinkedListNode::insert_tail( | ||
| 61 | (*(*TL_REF_TABLE.as_ptr()).mem_manager_table).pevt_free_buffer_queue, | ||
| 62 | node_ptr, | ||
| 63 | ); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | } | ||
| 67 | } | ||
diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32/src/tl_mbox/mod.rs deleted file mode 100644 index d39c78b2c..000000000 --- a/embassy-stm32/src/tl_mbox/mod.rs +++ /dev/null | |||
| @@ -1,417 +0,0 @@ | |||
| 1 | use core::mem::MaybeUninit; | ||
| 2 | |||
| 3 | use atomic_polyfill::{compiler_fence, Ordering}; | ||
| 4 | use bit_field::BitField; | ||
| 5 | use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; | ||
| 6 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||
| 7 | use embassy_sync::channel::Channel; | ||
| 8 | |||
| 9 | use self::ble::Ble; | ||
| 10 | use self::cmd::{AclDataPacket, CmdPacket}; | ||
| 11 | use self::evt::{CsEvt, EvtBox}; | ||
| 12 | use self::mm::MemoryManager; | ||
| 13 | use self::shci::{shci_ble_init, ShciBleInitCmdParam}; | ||
| 14 | use self::sys::Sys; | ||
| 15 | use self::unsafe_linked_list::LinkedListNode; | ||
| 16 | use crate::interrupt; | ||
| 17 | use crate::interrupt::InterruptExt; | ||
| 18 | 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 | |||
| 35 | const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::<PacketHeader>(); | ||
| 36 | const TL_EVT_HEADER_SIZE: usize = 3; | ||
| 37 | const TL_CS_EVT_SIZE: usize = core::mem::size_of::<CsEvt>(); | ||
| 38 | |||
| 39 | const CFG_TL_BLE_EVT_QUEUE_LENGTH: usize = 5; | ||
| 40 | const CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255; | ||
| 41 | const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE; | ||
| 42 | |||
| 43 | const POOL_SIZE: usize = CFG_TL_BLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); | ||
| 44 | |||
| 45 | const fn divc(x: usize, y: usize) -> usize { | ||
| 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 | |||
| 63 | /// Interrupt handler. | ||
| 64 | pub struct ReceiveInterruptHandler {} | ||
| 65 | |||
| 66 | impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_RX> for ReceiveInterruptHandler { | ||
| 67 | unsafe fn on_interrupt() { | ||
| 68 | // info!("ipcc rx interrupt"); | ||
| 69 | |||
| 70 | if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) { | ||
| 71 | sys::Sys::evt_handler(); | ||
| 72 | } else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) { | ||
| 73 | ble::Ble::evt_handler(); | ||
| 74 | } else { | ||
| 75 | todo!() | ||
| 76 | } | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | pub struct TransmitInterruptHandler {} | ||
| 81 | |||
| 82 | impl interrupt::typelevel::Handler<interrupt::typelevel::IPCC_C1_TX> for TransmitInterruptHandler { | ||
| 83 | unsafe fn on_interrupt() { | ||
| 84 | // info!("ipcc tx interrupt"); | ||
| 85 | |||
| 86 | if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) { | ||
| 87 | // TODO: handle this case | ||
| 88 | let _ = sys::Sys::cmd_evt_handler(); | ||
| 89 | } else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) { | ||
| 90 | mm::MemoryManager::evt_handler(); | ||
| 91 | } else { | ||
| 92 | todo!() | ||
| 93 | } | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | /// # Version | ||
| 98 | /// - 0 -> 3 = Build - 0: Untracked - 15:Released - x: Tracked version | ||
| 99 | /// - 4 -> 7 = branch - 0: Mass Market - x: ... | ||
| 100 | /// - 8 -> 15 = Subversion | ||
| 101 | /// - 16 -> 23 = Version minor | ||
| 102 | /// - 24 -> 31 = Version major | ||
| 103 | /// # Memory Size | ||
| 104 | /// - 0 -> 7 = Flash ( Number of 4k sector) | ||
| 105 | /// - 8 -> 15 = Reserved ( Shall be set to 0 - may be used as flash extension ) | ||
| 106 | /// - 16 -> 23 = SRAM2b ( Number of 1k sector) | ||
| 107 | /// - 24 -> 31 = SRAM2a ( Number of 1k sector) | ||
| 108 | #[repr(C, packed)] | ||
| 109 | #[derive(Copy, Clone)] | ||
| 110 | pub struct WirelessFwInfoTable { | ||
| 111 | version: u32, | ||
| 112 | memory_size: u32, | ||
| 113 | info_stack: u32, | ||
| 114 | reserved: u32, | ||
| 115 | } | ||
| 116 | |||
| 117 | impl WirelessFwInfoTable { | ||
| 118 | pub fn version_major(&self) -> u8 { | ||
| 119 | let version = self.version; | ||
| 120 | (version.get_bits(24..31) & 0xff) as u8 | ||
| 121 | } | ||
| 122 | |||
| 123 | pub fn version_minor(&self) -> u8 { | ||
| 124 | let version = self.version; | ||
| 125 | (version.get_bits(16..23) & 0xff) as u8 | ||
| 126 | } | ||
| 127 | |||
| 128 | pub fn subversion(&self) -> u8 { | ||
| 129 | let version = self.version; | ||
| 130 | (version.get_bits(8..15) & 0xff) as u8 | ||
| 131 | } | ||
| 132 | |||
| 133 | /// size of FLASH, expressed in number of 4K sectors | ||
| 134 | pub fn flash_size(&self) -> u8 { | ||
| 135 | let memory_size = self.memory_size; | ||
| 136 | (memory_size.get_bits(0..7) & 0xff) as u8 | ||
| 137 | } | ||
| 138 | |||
| 139 | /// size for SRAM2a, expressed in number of 1K sectors | ||
| 140 | pub fn sram2a_size(&self) -> u8 { | ||
| 141 | let memory_size = self.memory_size; | ||
| 142 | (memory_size.get_bits(24..31) & 0xff) as u8 | ||
| 143 | } | ||
| 144 | |||
| 145 | /// size of SRAM2b, expressed in number of 1K sectors | ||
| 146 | pub fn sram2b_size(&self) -> u8 { | ||
| 147 | let memory_size = self.memory_size; | ||
| 148 | (memory_size.get_bits(16..23) & 0xff) as u8 | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | #[repr(C, packed)] | ||
| 153 | #[derive(Copy, Clone)] | ||
| 154 | pub struct DeviceInfoTable { | ||
| 155 | pub safe_boot_info_table: SafeBootInfoTable, | ||
| 156 | pub fus_info_table: FusInfoTable, | ||
| 157 | pub wireless_fw_info_table: WirelessFwInfoTable, | ||
| 158 | } | ||
| 159 | |||
| 160 | #[repr(C, packed)] | ||
| 161 | struct BleTable { | ||
| 162 | pcmd_buffer: *mut CmdPacket, | ||
| 163 | pcs_buffer: *const u8, | ||
| 164 | pevt_queue: *const u8, | ||
| 165 | phci_acl_data_buffer: *mut AclDataPacket, | ||
| 166 | } | ||
| 167 | |||
| 168 | #[repr(C, packed)] | ||
| 169 | struct ThreadTable { | ||
| 170 | no_stack_buffer: *const u8, | ||
| 171 | cli_cmd_rsp_buffer: *const u8, | ||
| 172 | ot_cmd_rsp_buffer: *const u8, | ||
| 173 | } | ||
| 174 | |||
| 175 | #[repr(C, packed)] | ||
| 176 | struct SysTable { | ||
| 177 | pcmd_buffer: *mut CmdPacket, | ||
| 178 | sys_queue: *const LinkedListNode, | ||
| 179 | } | ||
| 180 | |||
| 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 | } | ||
| 187 | |||
| 188 | #[allow(dead_code)] // Not used currently but reserved | ||
| 189 | #[repr(C, packed)] | ||
| 190 | struct BleLldTable { | ||
| 191 | cmd_rsp_buffer: *const u8, | ||
| 192 | m0_cmd_buffer: *const u8, | ||
| 193 | } | ||
| 194 | |||
| 195 | #[allow(dead_code)] // Not used currently but reserved | ||
| 196 | #[repr(C, packed)] | ||
| 197 | struct ZigbeeTable { | ||
| 198 | notif_m0_to_m4_buffer: *const u8, | ||
| 199 | appli_cmd_m4_to_m0_buffer: *const u8, | ||
| 200 | request_m0_to_m4_buffer: *const u8, | ||
| 201 | } | ||
| 202 | |||
| 203 | #[repr(C, packed)] | ||
| 204 | struct MemManagerTable { | ||
| 205 | spare_ble_buffer: *const u8, | ||
| 206 | spare_sys_buffer: *const u8, | ||
| 207 | |||
| 208 | ble_pool: *const u8, | ||
| 209 | ble_pool_size: u32, | ||
| 210 | |||
| 211 | pevt_free_buffer_queue: *mut LinkedListNode, | ||
| 212 | |||
| 213 | traces_evt_pool: *const u8, | ||
| 214 | traces_pool_size: u32, | ||
| 215 | } | ||
| 216 | |||
| 217 | #[repr(C, packed)] | ||
| 218 | struct TracesTable { | ||
| 219 | traces_queue: *const u8, | ||
| 220 | } | ||
| 221 | |||
| 222 | #[repr(C, packed)] | ||
| 223 | struct Mac802_15_4Table { | ||
| 224 | pcmd_rsp_buffer: *const u8, | ||
| 225 | pnotack_buffer: *const u8, | ||
| 226 | evt_queue: *const u8, | ||
| 227 | } | ||
| 228 | |||
| 229 | /// reference table. Contains pointers to all other tables | ||
| 230 | #[repr(C, packed)] | ||
| 231 | #[derive(Copy, Clone)] | ||
| 232 | pub struct RefTable { | ||
| 233 | pub device_info_table: *const DeviceInfoTable, | ||
| 234 | ble_table: *const BleTable, | ||
| 235 | thread_table: *const ThreadTable, | ||
| 236 | sys_table: *const SysTable, | ||
| 237 | mem_manager_table: *const MemManagerTable, | ||
| 238 | traces_table: *const TracesTable, | ||
| 239 | 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 | } | ||
| 244 | |||
| 245 | #[link_section = "TL_REF_TABLE"] | ||
| 246 | pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit(); | ||
| 247 | |||
| 248 | #[link_section = "MB_MEM1"] | ||
| 249 | static mut TL_DEVICE_INFO_TABLE: MaybeUninit<DeviceInfoTable> = MaybeUninit::uninit(); | ||
| 250 | |||
| 251 | #[link_section = "MB_MEM1"] | ||
| 252 | static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit(); | ||
| 253 | |||
| 254 | #[link_section = "MB_MEM1"] | ||
| 255 | static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit(); | ||
| 256 | |||
| 257 | #[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(); | ||
| 265 | |||
| 266 | #[link_section = "MB_MEM1"] | ||
| 267 | static mut TL_MEM_MANAGER_TABLE: MaybeUninit<MemManagerTable> = MaybeUninit::uninit(); | ||
| 268 | |||
| 269 | #[link_section = "MB_MEM1"] | ||
| 270 | static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit(); | ||
| 271 | |||
| 272 | #[link_section = "MB_MEM1"] | ||
| 273 | static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit(); | ||
| 274 | |||
| 275 | #[link_section = "MB_MEM1"] | ||
| 276 | static mut TL_ZIGBEE_TABLE: MaybeUninit<ZigbeeTable> = MaybeUninit::uninit(); | ||
| 277 | |||
| 278 | #[allow(dead_code)] // Not used currently but reserved | ||
| 279 | #[link_section = "MB_MEM1"] | ||
| 280 | static mut FREE_BUFF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 281 | |||
| 282 | // not in shared RAM | ||
| 283 | static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 284 | |||
| 285 | #[link_section = "MB_MEM2"] | ||
| 286 | static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> = | ||
| 287 | MaybeUninit::uninit(); | ||
| 288 | |||
| 289 | #[link_section = "MB_MEM2"] | ||
| 290 | static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 291 | |||
| 292 | #[link_section = "MB_MEM2"] | ||
| 293 | static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 294 | |||
| 295 | #[link_section = "MB_MEM2"] | ||
| 296 | static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); | ||
| 297 | |||
| 298 | #[link_section = "MB_MEM2"] | ||
| 299 | static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit(); | ||
| 300 | |||
| 301 | #[link_section = "MB_MEM2"] | ||
| 302 | static mut SYS_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> = | ||
| 303 | MaybeUninit::uninit(); | ||
| 304 | |||
| 305 | #[link_section = "MB_MEM2"] | ||
| 306 | static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> = | ||
| 307 | MaybeUninit::uninit(); | ||
| 308 | |||
| 309 | #[link_section = "MB_MEM2"] | ||
| 310 | static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); | ||
| 311 | |||
| 312 | #[link_section = "MB_MEM2"] | ||
| 313 | // "magic" numbers from ST ---v---v | ||
| 314 | static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); | ||
| 315 | |||
| 316 | // TODO: get a better size, this is a placeholder | ||
| 317 | pub(crate) static TL_CHANNEL: Channel<CriticalSectionRawMutex, EvtBox, 5> = Channel::new(); | ||
| 318 | |||
| 319 | pub struct TlMbox<'d> { | ||
| 320 | _ipcc: PeripheralRef<'d, IPCC>, | ||
| 321 | } | ||
| 322 | |||
| 323 | impl<'d> TlMbox<'d> { | ||
| 324 | /// initializes low-level transport between CPU1 and BLE stack on CPU2 | ||
| 325 | pub fn new( | ||
| 326 | ipcc: impl Peripheral<P = IPCC> + 'd, | ||
| 327 | _irqs: impl interrupt::typelevel::Binding<interrupt::typelevel::IPCC_C1_RX, ReceiveInterruptHandler> | ||
| 328 | + interrupt::typelevel::Binding<interrupt::typelevel::IPCC_C1_TX, TransmitInterruptHandler>, | ||
| 329 | config: Config, | ||
| 330 | ) -> Self { | ||
| 331 | into_ref!(ipcc); | ||
| 332 | |||
| 333 | unsafe { | ||
| 334 | compiler_fence(Ordering::AcqRel); | ||
| 335 | |||
| 336 | TL_REF_TABLE.as_mut_ptr().write_volatile(RefTable { | ||
| 337 | device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(), | ||
| 338 | ble_table: TL_BLE_TABLE.as_ptr(), | ||
| 339 | thread_table: TL_THREAD_TABLE.as_ptr(), | ||
| 340 | sys_table: TL_SYS_TABLE.as_ptr(), | ||
| 341 | mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), | ||
| 342 | traces_table: TL_TRACES_TABLE.as_ptr(), | ||
| 343 | 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 | }); | ||
| 348 | |||
| 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(); | ||
| 354 | TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed(); | ||
| 355 | TL_BLE_TABLE = MaybeUninit::zeroed(); | ||
| 356 | TL_THREAD_TABLE = MaybeUninit::zeroed(); | ||
| 357 | TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed(); | ||
| 358 | TL_TRACES_TABLE = MaybeUninit::zeroed(); | ||
| 359 | 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 | |||
| 364 | EVT_POOL = MaybeUninit::zeroed(); | ||
| 365 | SYS_SPARE_EVT_BUF = MaybeUninit::zeroed(); | ||
| 366 | BLE_SPARE_EVT_BUF = MaybeUninit::zeroed(); | ||
| 367 | |||
| 368 | CS_BUFFER = MaybeUninit::zeroed(); | ||
| 369 | BLE_CMD_BUFFER = MaybeUninit::zeroed(); | ||
| 370 | HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed(); | ||
| 371 | |||
| 372 | compiler_fence(Ordering::AcqRel); | ||
| 373 | } | ||
| 374 | |||
| 375 | Ipcc::enable(config); | ||
| 376 | |||
| 377 | Sys::enable(); | ||
| 378 | Ble::enable(); | ||
| 379 | MemoryManager::enable(); | ||
| 380 | |||
| 381 | // enable interrupts | ||
| 382 | crate::interrupt::IPCC_C1_RX.unpend(); | ||
| 383 | crate::interrupt::IPCC_C1_TX.unpend(); | ||
| 384 | |||
| 385 | unsafe { crate::interrupt::IPCC_C1_RX.enable() }; | ||
| 386 | unsafe { crate::interrupt::IPCC_C1_TX.enable() }; | ||
| 387 | |||
| 388 | Self { _ipcc: ipcc } | ||
| 389 | } | ||
| 390 | |||
| 391 | pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> { | ||
| 392 | let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table }; | ||
| 393 | |||
| 394 | // zero version indicates that CPU2 wasn't active and didn't fill the information table | ||
| 395 | if info.version != 0 { | ||
| 396 | Some(*info) | ||
| 397 | } else { | ||
| 398 | None | ||
| 399 | } | ||
| 400 | } | ||
| 401 | |||
| 402 | pub fn shci_ble_init(&self, param: ShciBleInitCmdParam) { | ||
| 403 | shci_ble_init(param); | ||
| 404 | } | ||
| 405 | |||
| 406 | pub fn send_ble_cmd(&self, buf: &[u8]) { | ||
| 407 | ble::Ble::send_cmd(buf); | ||
| 408 | } | ||
| 409 | |||
| 410 | // pub fn send_sys_cmd(&self, buf: &[u8]) { | ||
| 411 | // sys::Sys::send_cmd(buf); | ||
| 412 | // } | ||
| 413 | |||
| 414 | pub async fn read(&self) -> EvtBox { | ||
| 415 | TL_CHANNEL.recv().await | ||
| 416 | } | ||
| 417 | } | ||
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 14897b171..83a443754 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml | |||
| @@ -9,6 +9,7 @@ embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["de | |||
| 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 9 | embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 10 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
| 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } | 11 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] } |
| 12 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } | ||
| 12 | 13 | ||
| 13 | defmt = "0.3" | 14 | defmt = "0.3" |
| 14 | defmt-rtt = "0.4" | 15 | defmt-rtt = "0.4" |
diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs index 8f4e70af0..ae36a7e79 100644 --- a/examples/stm32wb/src/bin/tl_mbox.rs +++ b/examples/stm32wb/src/bin/tl_mbox.rs | |||
| @@ -4,14 +4,15 @@ | |||
| 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::bind_interrupts; |
| 8 | use embassy_stm32::{bind_interrupts, tl_mbox}; | 8 | use embassy_stm32::ipcc::Config; |
| 9 | use embassy_stm32_wpan::TlMbox; | ||
| 9 | use embassy_time::{Duration, Timer}; | 10 | use embassy_time::{Duration, Timer}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 12 | ||
| 12 | bind_interrupts!(struct Irqs{ | 13 | bind_interrupts!(struct Irqs{ |
| 13 | IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler; | 14 | IPCC_C1_RX => embassy_stm32_wpan::ReceiveInterruptHandler; |
| 14 | IPCC_C1_TX => tl_mbox::TransmitInterruptHandler; | 15 | IPCC_C1_TX => embassy_stm32_wpan::TransmitInterruptHandler; |
| 15 | }); | 16 | }); |
| 16 | 17 | ||
| 17 | #[embassy_executor::main] | 18 | #[embassy_executor::main] |
| @@ -44,7 +45,7 @@ async fn main(_spawner: Spawner) { | |||
| 44 | info!("Hello World!"); | 45 | info!("Hello World!"); |
| 45 | 46 | ||
| 46 | let config = Config::default(); | 47 | let config = Config::default(); |
| 47 | let mbox = TlMbox::new(p.IPCC, Irqs, config); | 48 | let mbox = TlMbox::init(p.IPCC, Irqs, config); |
| 48 | 49 | ||
| 49 | loop { | 50 | loop { |
| 50 | let wireless_fw_info = mbox.wireless_fw_info(); | 51 | let wireless_fw_info = mbox.wireless_fw_info(); |
diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs index 1724d946f..3132ab3e4 100644 --- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs +++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs | |||
| @@ -4,13 +4,15 @@ | |||
| 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::bind_interrupts; |
| 8 | use embassy_stm32::{bind_interrupts, tl_mbox}; | 8 | use embassy_stm32::ipcc::Config; |
| 9 | use embassy_stm32_wpan::rc::RadioCoprocessor; | ||
| 10 | use embassy_stm32_wpan::TlMbox; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 12 | ||
| 11 | bind_interrupts!(struct Irqs{ | 13 | bind_interrupts!(struct Irqs{ |
| 12 | IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler; | 14 | IPCC_C1_RX => embassy_stm32_wpan::ReceiveInterruptHandler; |
| 13 | IPCC_C1_TX => tl_mbox::TransmitInterruptHandler; | 15 | IPCC_C1_TX => embassy_stm32_wpan::TransmitInterruptHandler; |
| 14 | }); | 16 | }); |
| 15 | 17 | ||
| 16 | #[embassy_executor::main] | 18 | #[embassy_executor::main] |
| @@ -43,55 +45,16 @@ async fn main(_spawner: Spawner) { | |||
| 43 | info!("Hello World!"); | 45 | info!("Hello World!"); |
| 44 | 46 | ||
| 45 | let config = Config::default(); | 47 | let config = Config::default(); |
| 46 | let mbox = TlMbox::new(p.IPCC, Irqs, config); | 48 | let mbox = TlMbox::init(p.IPCC, Irqs, config); |
| 47 | 49 | ||
| 48 | info!("waiting for coprocessor to boot"); | 50 | let mut rc = RadioCoprocessor::new(mbox); |
| 49 | let event_box = mbox.read().await; | ||
| 50 | 51 | ||
| 51 | let mut payload = [0u8; 6]; | 52 | let response = rc.read().await; |
| 52 | event_box.copy_into_slice(&mut payload).unwrap(); | 53 | info!("coprocessor ready {}", response); |
| 53 | 54 | ||
| 54 | let event_packet = event_box.evt(); | 55 | rc.write(&[0x01, 0x03, 0x0c, 0x00, 0x00]); |
| 55 | let kind = event_packet.evt_serial.kind; | 56 | let response = rc.read().await; |
| 56 | 57 | info!("ble reset rsp {}", response); | |
| 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(); |
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 3f48bf3f1..db97e929b 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml | |||
| @@ -12,7 +12,7 @@ stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo | |||
| 12 | stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo | 12 | stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo |
| 13 | stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo | 13 | stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo |
| 14 | stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo | 14 | stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo |
| 15 | stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble"] # Nucleo | 15 | stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "dep:embassy-stm32-wpan"] # Nucleo |
| 16 | stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo | 16 | stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo |
| 17 | stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board | 17 | stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board |
| 18 | 18 | ||
| @@ -29,6 +29,7 @@ embassy-executor = { version = "0.2.0", path = "../../embassy-executor", feature | |||
| 29 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] } | 29 | embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768", "defmt-timestamp-uptime"] } |
| 30 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] } | 30 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-any"] } |
| 31 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | 31 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } |
| 32 | embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", optional = true, features = ["defmt", "stm32wb55rg"] } | ||
| 32 | 33 | ||
| 33 | defmt = "0.3.0" | 34 | defmt = "0.3.0" |
| 34 | defmt-rtt = "0.4" | 35 | defmt-rtt = "0.4" |
diff --git a/tests/stm32/src/bin/tl_mbox.rs b/tests/stm32/src/bin/tl_mbox.rs index fab9f0e1b..0f643d578 100644 --- a/tests/stm32/src/bin/tl_mbox.rs +++ b/tests/stm32/src/bin/tl_mbox.rs | |||
| @@ -8,13 +8,14 @@ mod common; | |||
| 8 | 8 | ||
| 9 | use common::*; | 9 | use common::*; |
| 10 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 11 | use embassy_stm32::tl_mbox::{Config, TlMbox}; | 11 | use embassy_stm32::bind_interrupts; |
| 12 | use embassy_stm32::{bind_interrupts, tl_mbox}; | 12 | use embassy_stm32::ipcc::Config; |
| 13 | use embassy_stm32_wpan::TlMbox; | ||
| 13 | use embassy_time::{Duration, Timer}; | 14 | use embassy_time::{Duration, Timer}; |
| 14 | 15 | ||
| 15 | bind_interrupts!(struct Irqs{ | 16 | bind_interrupts!(struct Irqs{ |
| 16 | IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler; | 17 | IPCC_C1_RX => embassy_stm32_wpan::ReceiveInterruptHandler; |
| 17 | IPCC_C1_TX => tl_mbox::TransmitInterruptHandler; | 18 | IPCC_C1_TX => embassy_stm32_wpan::TransmitInterruptHandler; |
| 18 | }); | 19 | }); |
| 19 | 20 | ||
| 20 | #[embassy_executor::main] | 21 | #[embassy_executor::main] |
| @@ -23,7 +24,7 @@ async fn main(_spawner: Spawner) { | |||
| 23 | info!("Hello World!"); | 24 | info!("Hello World!"); |
| 24 | 25 | ||
| 25 | let config = Config::default(); | 26 | let config = Config::default(); |
| 26 | let mbox = TlMbox::new(p.IPCC, Irqs, config); | 27 | let mbox = TlMbox::init(p.IPCC, Irqs, config); |
| 27 | 28 | ||
| 28 | loop { | 29 | loop { |
| 29 | let wireless_fw_info = mbox.wireless_fw_info(); | 30 | let wireless_fw_info = mbox.wireless_fw_info(); |
