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