Merge #1424
1424: add TL maibox for stm32wb r=xoviat a=OueslatiGhaith Hello, This pull request is related to #1397 and #1401, inspired by #24, build upon the work done in #1405, and was tested on an stm32wb55rg. This pull request aims to add the transport layer mailbox for stm32wb microcontrollers. For now it's only capable of initializing it and getting the firmware information Co-authored-by: goueslati <ghaith.oueslati@habemus.com> Co-authored-by: Ghaith Oueslati <73850124+OueslatiGhaith@users.noreply.github.com> Co-authored-by: xoviat <xoviat@users.noreply.github.com>
This commit is contained in:
@ -67,6 +67,7 @@ seq-macro = "0.3.0"
|
||||
cfg-if = "1.0.0"
|
||||
embedded-io = { version = "0.4.0", features = ["async"], optional = true }
|
||||
chrono = { version = "^0.4", default-features = false, optional = true}
|
||||
bit_field = "0.10.2"
|
||||
|
||||
[dev-dependencies]
|
||||
critical-section = { version = "1.1", features = ["std"] }
|
||||
@ -1443,4 +1444,4 @@ stm32wle5cb = [ "stm32-metapac/stm32wle5cb" ]
|
||||
stm32wle5cc = [ "stm32-metapac/stm32wle5cc" ]
|
||||
stm32wle5j8 = [ "stm32-metapac/stm32wle5j8" ]
|
||||
stm32wle5jb = [ "stm32-metapac/stm32wle5jb" ]
|
||||
stm32wle5jc = [ "stm32-metapac/stm32wle5jc" ]
|
||||
stm32wle5jc = [ "stm32-metapac/stm32wle5jc" ]
|
@ -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: *mut 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 = "MB_MEM1"]
|
||||
static mut TL_DEVICE_INFO_TABLE: MaybeUninit<DeviceInfoTable> = MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM1"]
|
||||
static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM1"]
|
||||
static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM1"]
|
||||
static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM1"]
|
||||
static mut TL_MEM_MANAGER_TABLE: MaybeUninit<MemManagerTable> = MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM1"]
|
||||
static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM1"]
|
||||
static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit();
|
||||
|
||||
#[allow(dead_code)] // Not used currently but reserved
|
||||
#[link_section = "MB_MEM2"]
|
||||
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 = "MB_MEM2"]
|
||||
static mut TRACES_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM2"]
|
||||
static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> =
|
||||
MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM2"]
|
||||
static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM2"]
|
||||
static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM2"]
|
||||
static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM2"]
|
||||
static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM2"]
|
||||
static mut SYS_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
|
||||
MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM2"]
|
||||
static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
|
||||
MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM2"]
|
||||
static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
|
||||
|
||||
#[link_section = "MB_MEM2"]
|
||||
// "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;
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user