added TL Mailbox initialization for STM32WB
This commit is contained in:
parent
6096f0cf4b
commit
bab30a7e87
11 changed files with 2063 additions and 1334 deletions
File diff suppressed because it is too large
Load diff
|
@ -57,6 +57,8 @@ pub mod rtc;
|
|||
pub mod sdmmc;
|
||||
#[cfg(spi)]
|
||||
pub mod spi;
|
||||
#[cfg(stm32wb)]
|
||||
pub mod tl_mbox;
|
||||
#[cfg(usart)]
|
||||
pub mod usart;
|
||||
#[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 a new issue