added TL Mailbox initialization for STM32WB
This commit is contained in:
parent
6096f0cf4b
commit
bab30a7e87
@ -67,6 +67,7 @@ seq-macro = "0.3.0"
|
|||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
embedded-io = { version = "0.4.0", features = ["async"], optional = true }
|
embedded-io = { version = "0.4.0", features = ["async"], optional = true }
|
||||||
chrono = { version = "^0.4", default-features = false, optional = true}
|
chrono = { version = "^0.4", default-features = false, optional = true}
|
||||||
|
bit_field = "0.10.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
critical-section = { version = "1.1", features = ["std"] }
|
critical-section = { version = "1.1", features = ["std"] }
|
||||||
|
@ -57,6 +57,8 @@ pub mod rtc;
|
|||||||
pub mod sdmmc;
|
pub mod sdmmc;
|
||||||
#[cfg(spi)]
|
#[cfg(spi)]
|
||||||
pub mod spi;
|
pub mod spi;
|
||||||
|
#[cfg(stm32wb)]
|
||||||
|
pub mod tl_mbox;
|
||||||
#[cfg(usart)]
|
#[cfg(usart)]
|
||||||
pub mod usart;
|
pub mod usart;
|
||||||
#[cfg(all(usb, feature = "time"))]
|
#[cfg(all(usb, feature = "time"))]
|
||||||
|
26
embassy-stm32/src/tl_mbox/ble.rs
Normal file
26
embassy-stm32/src/tl_mbox/ble.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
|
use super::unsafe_linked_list::LST_init_head;
|
||||||
|
use super::{channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE};
|
||||||
|
use crate::ipcc::Ipcc;
|
||||||
|
|
||||||
|
pub struct Ble;
|
||||||
|
|
||||||
|
impl Ble {
|
||||||
|
pub fn new(ipcc: &mut Ipcc) -> Self {
|
||||||
|
unsafe {
|
||||||
|
LST_init_head(EVT_QUEUE.as_mut_ptr());
|
||||||
|
|
||||||
|
TL_BLE_TABLE = MaybeUninit::new(BleTable {
|
||||||
|
pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(),
|
||||||
|
pcs_buffer: CS_BUFFER.as_mut_ptr().cast(),
|
||||||
|
pevt_queue: EVT_QUEUE.as_ptr().cast(),
|
||||||
|
phci_acl_data_buffer: HCI_ACL_DATA_BUFFER.as_mut_ptr().cast(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ipcc.c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true);
|
||||||
|
|
||||||
|
Ble
|
||||||
|
}
|
||||||
|
}
|
104
embassy-stm32/src/tl_mbox/channels.rs
Normal file
104
embassy-stm32/src/tl_mbox/channels.rs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
//! CPU1 CPU2
|
||||||
|
//! | (SYSTEM) |
|
||||||
|
//! |----HW_IPCC_SYSTEM_CMD_RSP_CHANNEL-------------->|
|
||||||
|
//! | |
|
||||||
|
//! |<---HW_IPCC_SYSTEM_EVENT_CHANNEL-----------------|
|
||||||
|
//! | |
|
||||||
|
//! | (ZIGBEE) |
|
||||||
|
//! |----HW_IPCC_ZIGBEE_CMD_APPLI_CHANNEL------------>|
|
||||||
|
//! | |
|
||||||
|
//! |----HW_IPCC_ZIGBEE_CMD_CLI_CHANNEL-------------->|
|
||||||
|
//! | |
|
||||||
|
//! |<---HW_IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL-------|
|
||||||
|
//! | |
|
||||||
|
//! |<---HW_IPCC_ZIGBEE_CLI_NOTIF_ACK_CHANNEL---------|
|
||||||
|
//! | |
|
||||||
|
//! | (THREAD) |
|
||||||
|
//! |----HW_IPCC_THREAD_OT_CMD_RSP_CHANNEL----------->|
|
||||||
|
//! | |
|
||||||
|
//! |----HW_IPCC_THREAD_CLI_CMD_CHANNEL-------------->|
|
||||||
|
//! | |
|
||||||
|
//! |<---HW_IPCC_THREAD_NOTIFICATION_ACK_CHANNEL------|
|
||||||
|
//! | |
|
||||||
|
//! |<---HW_IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL--|
|
||||||
|
//! | |
|
||||||
|
//! | (BLE) |
|
||||||
|
//! |----HW_IPCC_BLE_CMD_CHANNEL--------------------->|
|
||||||
|
//! | |
|
||||||
|
//! |----HW_IPCC_HCI_ACL_DATA_CHANNEL---------------->|
|
||||||
|
//! | |
|
||||||
|
//! |<---HW_IPCC_BLE_EVENT_CHANNEL--------------------|
|
||||||
|
//! | |
|
||||||
|
//! | (BLE LLD) |
|
||||||
|
//! |----HW_IPCC_BLE_LLD_CMD_CHANNEL----------------->|
|
||||||
|
//! | |
|
||||||
|
//! |<---HW_IPCC_BLE_LLD_RSP_CHANNEL------------------|
|
||||||
|
//! | |
|
||||||
|
//! |<---HW_IPCC_BLE_LLD_M0_CMD_CHANNEL---------------|
|
||||||
|
//! | |
|
||||||
|
//! | (MAC) |
|
||||||
|
//! |----HW_IPCC_MAC_802_15_4_CMD_RSP_CHANNEL-------->|
|
||||||
|
//! | |
|
||||||
|
//! |<---HW_IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL|
|
||||||
|
//! | |
|
||||||
|
//! | (BUFFER) |
|
||||||
|
//! |----HW_IPCC_MM_RELEASE_BUFFER_CHANNE------------>|
|
||||||
|
//! | |
|
||||||
|
//! | (TRACE) |
|
||||||
|
//! |<----HW_IPCC_TRACES_CHANNEL----------------------|
|
||||||
|
//! | |
|
||||||
|
//!
|
||||||
|
|
||||||
|
pub mod cpu1 {
|
||||||
|
use crate::ipcc::IpccChannel;
|
||||||
|
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_SYSTEM_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel2;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_THREAD_OT_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_ZIGBEE_CMD_APPLI_CHANNEL: IpccChannel = IpccChannel::Channel3;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_MAC_802_15_4_CMD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel3;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_MM_RELEASE_BUFFER_CHANNEL: IpccChannel = IpccChannel::Channel4;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_THREAD_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_LLDTESTS_CLI_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_BLE_LLD_CMD_CHANNEL: IpccChannel = IpccChannel::Channel5;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_HCI_ACL_DATA_CHANNEL: IpccChannel = IpccChannel::Channel6;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod cpu2 {
|
||||||
|
use crate::ipcc::IpccChannel;
|
||||||
|
|
||||||
|
pub const IPCC_BLE_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel1;
|
||||||
|
pub const IPCC_SYSTEM_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel2;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_THREAD_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_ZIGBEE_APPLI_NOTIF_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_MAC_802_15_4_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel3;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_LDDTESTS_M0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_BLE_LLDÇM0_CMD_CHANNEL: IpccChannel = IpccChannel::Channel3;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_TRACES_CHANNEL: IpccChannel = IpccChannel::Channel4;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_THREAD_CLI_NOTIFICATION_ACK_CHANNEL: IpccChannel = IpccChannel::Channel5;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_LLDTESTS_CLI_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_BLE_LLD_CLI_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_BLE_LLD_RSP_CHANNEL: IpccChannel = IpccChannel::Channel5;
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
pub const IPCC_ZIGBEE_M0_REQUEST_CHANNEL: IpccChannel = IpccChannel::Channel5;
|
||||||
|
}
|
49
embassy-stm32/src/tl_mbox/cmd.rs
Normal file
49
embassy-stm32/src/tl_mbox/cmd.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use super::PacketHeader;
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Cmd {
|
||||||
|
pub cmd_code: u16,
|
||||||
|
pub payload_len: u8,
|
||||||
|
pub payload: [u8; 255],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Cmd {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
cmd_code: 0,
|
||||||
|
payload_len: 0,
|
||||||
|
payload: [0u8; 255],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Copy, Clone, Default)]
|
||||||
|
pub struct CmdSerial {
|
||||||
|
pub ty: u8,
|
||||||
|
pub cmd: Cmd,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Copy, Clone, Default)]
|
||||||
|
pub struct CmdPacket {
|
||||||
|
pub header: PacketHeader,
|
||||||
|
pub cmd_serial: CmdSerial,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct AclDataSerial {
|
||||||
|
pub ty: u8,
|
||||||
|
pub handle: u16,
|
||||||
|
pub length: u16,
|
||||||
|
pub acl_data: [u8; 1],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct AclDataPacket {
|
||||||
|
pub header: PacketHeader,
|
||||||
|
pub acl_data_serial: AclDataSerial,
|
||||||
|
}
|
8
embassy-stm32/src/tl_mbox/evt.rs
Normal file
8
embassy-stm32/src/tl_mbox/evt.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/// the payload of [`Evt`] for a command status event
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C, packed)]
|
||||||
|
pub struct CsEvt {
|
||||||
|
pub status: u8,
|
||||||
|
pub num_cmd: u8,
|
||||||
|
pub cmd_code: u16,
|
||||||
|
}
|
30
embassy-stm32/src/tl_mbox/mm.rs
Normal file
30
embassy-stm32/src/tl_mbox/mm.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
|
use super::unsafe_linked_list::LST_init_head;
|
||||||
|
use super::{
|
||||||
|
MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUFF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, SYS_SPARE_EVT_BUF,
|
||||||
|
TL_MEM_MANAGER_TABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct MemoryManager;
|
||||||
|
|
||||||
|
impl MemoryManager {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
unsafe {
|
||||||
|
LST_init_head(FREE_BUFF_QUEUE.as_mut_ptr());
|
||||||
|
LST_init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr());
|
||||||
|
|
||||||
|
TL_MEM_MANAGER_TABLE = MaybeUninit::new(MemManagerTable {
|
||||||
|
spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(),
|
||||||
|
spare_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(),
|
||||||
|
ble_pool: EVT_POOL.as_ptr().cast(),
|
||||||
|
ble_pool_size: POOL_SIZE as u32,
|
||||||
|
pevt_free_buffer_queue: FREE_BUFF_QUEUE.as_mut_ptr(),
|
||||||
|
traces_evt_pool: core::ptr::null(),
|
||||||
|
traces_pool_size: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryManager
|
||||||
|
}
|
||||||
|
}
|
318
embassy-stm32/src/tl_mbox/mod.rs
Normal file
318
embassy-stm32/src/tl_mbox/mod.rs
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
|
use bit_field::BitField;
|
||||||
|
|
||||||
|
use self::ble::Ble;
|
||||||
|
use self::cmd::{AclDataPacket, CmdPacket};
|
||||||
|
use self::evt::CsEvt;
|
||||||
|
use self::mm::MemoryManager;
|
||||||
|
use self::sys::Sys;
|
||||||
|
use self::unsafe_linked_list::LinkedListNode;
|
||||||
|
use crate::ipcc::Ipcc;
|
||||||
|
|
||||||
|
mod ble;
|
||||||
|
mod channels;
|
||||||
|
mod cmd;
|
||||||
|
mod evt;
|
||||||
|
mod mm;
|
||||||
|
mod sys;
|
||||||
|
mod unsafe_linked_list;
|
||||||
|
|
||||||
|
pub type PacketHeader = LinkedListNode;
|
||||||
|
|
||||||
|
const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::<PacketHeader>();
|
||||||
|
const TL_EVT_HEADER_SIZE: usize = 3;
|
||||||
|
const TL_CS_EVT_SIZE: usize = core::mem::size_of::<CsEvt>();
|
||||||
|
|
||||||
|
const CFG_TL_BLE_EVT_QUEUE_LENGTH: usize = 5;
|
||||||
|
const CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255;
|
||||||
|
const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE;
|
||||||
|
|
||||||
|
const POOL_SIZE: usize = CFG_TL_BLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4);
|
||||||
|
|
||||||
|
const fn divc(x: usize, y: usize) -> usize {
|
||||||
|
(x + y - 1) / y
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct SafeBootInfoTable {
|
||||||
|
version: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct RssInfoTable {
|
||||||
|
version: u32,
|
||||||
|
memory_size: u32,
|
||||||
|
rss_info: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Version
|
||||||
|
/// - 0 -> 3 = Build - 0: Untracked - 15:Released - x: Tracked version
|
||||||
|
/// - 4 -> 7 = branch - 0: Mass Market - x: ...
|
||||||
|
/// - 8 -> 15 = Subversion
|
||||||
|
/// - 16 -> 23 = Version minor
|
||||||
|
/// - 24 -> 31 = Version major
|
||||||
|
/// # Memory Size
|
||||||
|
/// - 0 -> 7 = Flash ( Number of 4k sector)
|
||||||
|
/// - 8 -> 15 = Reserved ( Shall be set to 0 - may be used as flash extension )
|
||||||
|
/// - 16 -> 23 = SRAM2b ( Number of 1k sector)
|
||||||
|
/// - 24 -> 31 = SRAM2a ( Number of 1k sector)
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct WirelessFwInfoTable {
|
||||||
|
version: u32,
|
||||||
|
memory_size: u32,
|
||||||
|
thread_info: u32,
|
||||||
|
ble_info: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WirelessFwInfoTable {
|
||||||
|
pub fn version_major(&self) -> u8 {
|
||||||
|
let version = self.version;
|
||||||
|
(version.get_bits(24..31) & 0xff) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn version_minor(&self) -> u8 {
|
||||||
|
let version = self.version;
|
||||||
|
(version.get_bits(16..23) & 0xff) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subversion(&self) -> u8 {
|
||||||
|
let version = self.version;
|
||||||
|
(version.get_bits(8..15) & 0xff) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
/// size of FLASH, expressed in number of 4K sectors
|
||||||
|
pub fn flash_size(&self) -> u8 {
|
||||||
|
let memory_size = self.memory_size;
|
||||||
|
(memory_size.get_bits(0..7) & 0xff) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
/// size for SRAM2a, expressed in number of 1K sectors
|
||||||
|
pub fn sram2a_size(&self) -> u8 {
|
||||||
|
let memory_size = self.memory_size;
|
||||||
|
(memory_size.get_bits(24..31) & 0xff) as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
/// size of SRAM2b, expressed in number of 1K sectors
|
||||||
|
pub fn sram2b_size(&self) -> u8 {
|
||||||
|
let memory_size = self.memory_size;
|
||||||
|
(memory_size.get_bits(16..23) & 0xff) as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct DeviceInfoTable {
|
||||||
|
pub safe_boot_info_table: SafeBootInfoTable,
|
||||||
|
pub rss_info_table: RssInfoTable,
|
||||||
|
pub wireless_fw_info_table: WirelessFwInfoTable,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct BleTable {
|
||||||
|
pcmd_buffer: *const CmdPacket,
|
||||||
|
pcs_buffer: *const u8,
|
||||||
|
pevt_queue: *const u8,
|
||||||
|
phci_acl_data_buffer: *mut AclDataPacket,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct ThreadTable {
|
||||||
|
no_stack_buffer: *const u8,
|
||||||
|
cli_cmd_rsp_buffer: *const u8,
|
||||||
|
ot_cmd_rsp_buffer: *const u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct SysTable {
|
||||||
|
pcmd_buffer: *mut CmdPacket,
|
||||||
|
sys_queue: *const LinkedListNode,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct LldTestTable {
|
||||||
|
cli_cmd_rsp_buffer: *const u8,
|
||||||
|
m0_cmd_buffer: *const u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct BleLldTable {
|
||||||
|
cmd_rsp_buffer: *const u8,
|
||||||
|
m0_cmd_buffer: *const u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct ZigbeeTable {
|
||||||
|
notif_m0_to_m4_buffer: *const u8,
|
||||||
|
appli_cmd_m4_to_m0_buffer: *const u8,
|
||||||
|
request_m0_to_m4_buffer: *const u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct MemManagerTable {
|
||||||
|
spare_ble_buffer: *const u8,
|
||||||
|
spare_sys_buffer: *const u8,
|
||||||
|
|
||||||
|
ble_pool: *const u8,
|
||||||
|
ble_pool_size: u32,
|
||||||
|
|
||||||
|
pevt_free_buffer_queue: *mut LinkedListNode,
|
||||||
|
|
||||||
|
traces_evt_pool: *const u8,
|
||||||
|
traces_pool_size: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct TracesTable {
|
||||||
|
traces_queue: *const u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C, packed)]
|
||||||
|
struct Mac802_15_4Table {
|
||||||
|
pcmd_rsp_buffer: *const u8,
|
||||||
|
pnotack_buffer: *const u8,
|
||||||
|
evt_queue: *const u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// reference table. Contains pointers to all other tables
|
||||||
|
#[repr(C, packed)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct RefTable {
|
||||||
|
pub device_info_table: *const DeviceInfoTable,
|
||||||
|
ble_table: *const BleTable,
|
||||||
|
thread_table: *const ThreadTable,
|
||||||
|
sys_table: *const SysTable,
|
||||||
|
mem_manager_table: *const MemManagerTable,
|
||||||
|
traces_table: *const TracesTable,
|
||||||
|
mac_802_15_4_table: *const Mac802_15_4Table,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[link_section = "TL_REF_TABLE"]
|
||||||
|
pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "TL_DEVICE_INFO_TABLE"]
|
||||||
|
static mut TL_DEVICE_INFO_TABLE: MaybeUninit<DeviceInfoTable> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "TL_BLE_TABLE"]
|
||||||
|
static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "TL_THREAD_TABLE"]
|
||||||
|
static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "TL_SYS_TABLE"]
|
||||||
|
static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "TL_MEM_MANAGER_TABLE"]
|
||||||
|
static mut TL_MEM_MANAGER_TABLE: MaybeUninit<MemManagerTable> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "TL_TRACES_TABLE"]
|
||||||
|
static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "TL_MAC_802_15_4_TABLE"]
|
||||||
|
static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
#[link_section = "FREE_BUF_QUEUE"]
|
||||||
|
static mut FREE_BUFF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
// not in shared RAM
|
||||||
|
static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[allow(dead_code)] // Not used currently but reserved
|
||||||
|
#[link_section = "TRACES_EVT_QUEUE"]
|
||||||
|
static mut TRACES_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "CS_BUFFER"]
|
||||||
|
static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> =
|
||||||
|
MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "EVT_QUEUE"]
|
||||||
|
static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "SYSTEM_EVT_QUEUE"]
|
||||||
|
static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "SYS_CMD_BUF"]
|
||||||
|
static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "EVT_POOL"]
|
||||||
|
static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "SYS_SPARE_EVT_BUF"]
|
||||||
|
static mut SYS_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
|
||||||
|
MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "BLE_SPARE_EVT_BUF"]
|
||||||
|
static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
|
||||||
|
MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "BLE_CMD_BUFFER"]
|
||||||
|
static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
#[link_section = "HCI_ACL_DATA_BUFFER"]
|
||||||
|
// "magic" numbers from ST ---v---v
|
||||||
|
static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit();
|
||||||
|
|
||||||
|
pub struct TlMbox {
|
||||||
|
_sys: Sys,
|
||||||
|
_ble: Ble,
|
||||||
|
_mm: MemoryManager,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlMbox {
|
||||||
|
/// initializes low-level transport between CPU1 and BLE stack on CPU2
|
||||||
|
pub fn init(ipcc: &mut Ipcc) -> TlMbox {
|
||||||
|
unsafe {
|
||||||
|
TL_REF_TABLE = MaybeUninit::new(RefTable {
|
||||||
|
device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(),
|
||||||
|
ble_table: TL_BLE_TABLE.as_ptr(),
|
||||||
|
thread_table: TL_THREAD_TABLE.as_ptr(),
|
||||||
|
sys_table: TL_SYS_TABLE.as_ptr(),
|
||||||
|
mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(),
|
||||||
|
traces_table: TL_TRACES_TABLE.as_ptr(),
|
||||||
|
mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(),
|
||||||
|
});
|
||||||
|
|
||||||
|
TL_SYS_TABLE = MaybeUninit::zeroed();
|
||||||
|
TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed();
|
||||||
|
TL_BLE_TABLE = MaybeUninit::zeroed();
|
||||||
|
TL_THREAD_TABLE = MaybeUninit::zeroed();
|
||||||
|
TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed();
|
||||||
|
TL_TRACES_TABLE = MaybeUninit::zeroed();
|
||||||
|
TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed();
|
||||||
|
|
||||||
|
EVT_POOL = MaybeUninit::zeroed();
|
||||||
|
SYS_SPARE_EVT_BUF = MaybeUninit::zeroed();
|
||||||
|
BLE_SPARE_EVT_BUF = MaybeUninit::zeroed();
|
||||||
|
|
||||||
|
CS_BUFFER = MaybeUninit::zeroed();
|
||||||
|
BLE_CMD_BUFFER = MaybeUninit::zeroed();
|
||||||
|
HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed();
|
||||||
|
}
|
||||||
|
|
||||||
|
ipcc.init();
|
||||||
|
|
||||||
|
let _sys = Sys::new(ipcc);
|
||||||
|
let _ble = Ble::new(ipcc);
|
||||||
|
let _mm = MemoryManager::new();
|
||||||
|
|
||||||
|
TlMbox { _sys, _ble, _mm }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> {
|
||||||
|
let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table };
|
||||||
|
|
||||||
|
// zero version indicates that CPU2 wasn't active and didn't fill the information table
|
||||||
|
if info.version != 0 {
|
||||||
|
Some(*info)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
embassy-stm32/src/tl_mbox/sys.rs
Normal file
24
embassy-stm32/src/tl_mbox/sys.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
|
use super::unsafe_linked_list::LST_init_head;
|
||||||
|
use super::{channels, SysTable, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_SYS_TABLE};
|
||||||
|
use crate::ipcc::Ipcc;
|
||||||
|
|
||||||
|
pub struct Sys;
|
||||||
|
|
||||||
|
impl Sys {
|
||||||
|
pub fn new(ipcc: &mut Ipcc) -> Self {
|
||||||
|
unsafe {
|
||||||
|
LST_init_head(SYSTEM_EVT_QUEUE.as_mut_ptr());
|
||||||
|
|
||||||
|
TL_SYS_TABLE = MaybeUninit::new(SysTable {
|
||||||
|
pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(),
|
||||||
|
sys_queue: SYSTEM_EVT_QUEUE.as_ptr(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ipcc.c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true);
|
||||||
|
|
||||||
|
Sys
|
||||||
|
}
|
||||||
|
}
|
123
embassy-stm32/src/tl_mbox/unsafe_linked_list.rs
Normal file
123
embassy-stm32/src/tl_mbox/unsafe_linked_list.rs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
//! Unsafe linked list.
|
||||||
|
//! Translated from ST's C by `c2rust` tool.
|
||||||
|
|
||||||
|
#![allow(
|
||||||
|
dead_code,
|
||||||
|
mutable_transmutes,
|
||||||
|
non_camel_case_types,
|
||||||
|
non_snake_case,
|
||||||
|
non_upper_case_globals,
|
||||||
|
unused_assignments,
|
||||||
|
unused_mut
|
||||||
|
)]
|
||||||
|
|
||||||
|
use cortex_m::interrupt;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C, packed(4))]
|
||||||
|
pub struct LinkedListNode {
|
||||||
|
pub next: *mut LinkedListNode,
|
||||||
|
pub prev: *mut LinkedListNode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for LinkedListNode {
|
||||||
|
fn default() -> Self {
|
||||||
|
LinkedListNode {
|
||||||
|
next: core::ptr::null_mut(),
|
||||||
|
prev: core::ptr::null_mut(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn LST_init_head(mut listHead: *mut LinkedListNode) {
|
||||||
|
(*listHead).next = listHead;
|
||||||
|
(*listHead).prev = listHead;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn LST_is_empty(mut listHead: *mut LinkedListNode) -> bool {
|
||||||
|
interrupt::free(|_| ((*listHead).next) == listHead)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn LST_insert_head(mut listHead: *mut LinkedListNode, mut node: *mut LinkedListNode) {
|
||||||
|
interrupt::free(|_| {
|
||||||
|
(*node).next = (*listHead).next;
|
||||||
|
(*node).prev = listHead;
|
||||||
|
(*listHead).next = node;
|
||||||
|
(*(*node).next).prev = node;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn LST_insert_tail(mut listHead: *mut LinkedListNode, mut node: *mut LinkedListNode) {
|
||||||
|
interrupt::free(|_| {
|
||||||
|
(*node).next = listHead;
|
||||||
|
(*node).prev = (*listHead).prev;
|
||||||
|
(*listHead).prev = node;
|
||||||
|
(*(*node).prev).next = node;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn LST_remove_node(mut node: *mut LinkedListNode) {
|
||||||
|
interrupt::free(|_| {
|
||||||
|
(*(*node).prev).next = (*node).next;
|
||||||
|
(*(*node).next).prev = (*node).prev;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn LST_remove_head(mut listHead: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
|
||||||
|
interrupt::free(|_| {
|
||||||
|
*node = (*listHead).next;
|
||||||
|
LST_remove_node((*listHead).next);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn LST_remove_tail(mut listHead: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
|
||||||
|
interrupt::free(|_| {
|
||||||
|
*node = (*listHead).prev;
|
||||||
|
LST_remove_node((*listHead).prev);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn LST_insert_node_after(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) {
|
||||||
|
interrupt::free(|_| {
|
||||||
|
(*node).next = (*ref_node).next;
|
||||||
|
(*node).prev = ref_node;
|
||||||
|
(*ref_node).next = node;
|
||||||
|
(*(*node).next).prev = node;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn LST_insert_node_before(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) {
|
||||||
|
interrupt::free(|_| {
|
||||||
|
(*node).next = ref_node;
|
||||||
|
(*node).prev = (*ref_node).prev;
|
||||||
|
(*ref_node).prev = node;
|
||||||
|
(*(*node).prev).next = node;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn LST_get_size(mut listHead: *mut LinkedListNode) -> usize {
|
||||||
|
interrupt::free(|_| {
|
||||||
|
let mut size = 0;
|
||||||
|
let mut temp: *mut LinkedListNode = core::ptr::null_mut::<LinkedListNode>();
|
||||||
|
|
||||||
|
temp = (*listHead).next;
|
||||||
|
while temp != listHead {
|
||||||
|
size += 1;
|
||||||
|
temp = (*temp).next
|
||||||
|
}
|
||||||
|
|
||||||
|
size
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn LST_get_next_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
|
||||||
|
interrupt::free(|_| {
|
||||||
|
*node = (*ref_node).next;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn LST_get_prev_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
|
||||||
|
interrupt::free(|_| {
|
||||||
|
*node = (*ref_node).prev;
|
||||||
|
});
|
||||||
|
}
|
44
examples/stm32wb/src/bin/tl_mbox.rs
Normal file
44
examples/stm32wb/src/bin/tl_mbox.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::ipcc::{Config, Ipcc};
|
||||||
|
use embassy_stm32::tl_mbox::TlMbox;
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) {
|
||||||
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
info!("Hello World!");
|
||||||
|
|
||||||
|
let config = Config::default();
|
||||||
|
let mut ipcc = Ipcc::new(p.IPCC, config);
|
||||||
|
|
||||||
|
let mbox = TlMbox::init(&mut ipcc);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let wireless_fw_info = mbox.wireless_fw_info();
|
||||||
|
match wireless_fw_info {
|
||||||
|
None => error!("not yet initialized"),
|
||||||
|
Some(fw_info) => {
|
||||||
|
let version_major = fw_info.version_major();
|
||||||
|
let version_minor = fw_info.version_minor();
|
||||||
|
let subversion = fw_info.subversion();
|
||||||
|
|
||||||
|
let sram2a_size = fw_info.sram2a_size();
|
||||||
|
let sram2b_size = fw_info.sram2b_size();
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"version {}.{}.{} - SRAM2a {} - SRAM2b {}",
|
||||||
|
version_major, version_minor, subversion, sram2a_size, sram2b_size
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user