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:
commit
7f96359804
17 changed files with 830 additions and 22 deletions
3
.vscode/.gitignore
vendored
Normal file
3
.vscode/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
*.cortex-debug.*.json
|
||||
launch.json
|
||||
tasks.json
|
|
@ -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;
|
||||
});
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||
# replace STM32WB55CCUx with your chip as listed in `probe-rs-cli chip list`
|
||||
runner = "probe-rs-cli run --chip STM32WB55CCUx --speed 1000 --connect-under-reset"
|
||||
# runner = "probe-rs-cli run --chip STM32WB55CCUx --speed 1000 --connect-under-reset"
|
||||
runner = "teleprobe local run --chip STM32WB55RG --elf"
|
||||
|
||||
[build]
|
||||
target = "thumbv7em-none-eabihf"
|
||||
|
|
|
@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
|
|||
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||
embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55cc", "time-driver-any", "exti"] }
|
||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "exti"] }
|
||||
|
||||
defmt = "0.3"
|
||||
defmt-rtt = "0.4"
|
||||
|
|
|
@ -10,6 +10,17 @@ MEMORY
|
|||
RAM_SHARED (xrw) : ORIGIN = 0x20030000, LENGTH = 10K
|
||||
}
|
||||
|
||||
/*
|
||||
Memory size for STM32WB55xC with 512K FLASH
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
|
||||
RAM (xrw) : ORIGIN = 0x20000008, LENGTH = 0x2FFF8
|
||||
RAM_SHARED (xrw) : ORIGIN = 0x20030000, LENGTH = 10K
|
||||
}
|
||||
*/
|
||||
|
||||
/* Place stack at the end of SRAM1 */
|
||||
_stack_start = ORIGIN(RAM) + LENGTH(RAM);
|
||||
|
||||
|
@ -19,23 +30,6 @@ _stack_start = ORIGIN(RAM) + LENGTH(RAM);
|
|||
SECTIONS {
|
||||
TL_REF_TABLE (NOLOAD) : { *(TL_REF_TABLE) } >RAM_SHARED
|
||||
|
||||
TL_DEVICE_INFO_TABLE 0x2003001c (NOLOAD) : { *(TL_DEVICE_INFO_TABLE) } >RAM_SHARED
|
||||
TL_BLE_TABLE 0x2003003c (NOLOAD) : { *(TL_BLE_TABLE) } >RAM_SHARED
|
||||
TL_THREAD_TABLE 0x2003004c (NOLOAD) : { *(TL_THREAD_TABLE) } >RAM_SHARED
|
||||
TL_SYS_TABLE 0x20030058 (NOLOAD) : { *(TL_SYS_TABLE) } >RAM_SHARED
|
||||
TL_MEM_MANAGER_TABLE 0x20030060 (NOLOAD) : { *(TL_MEM_MANAGER_TABLE) } >RAM_SHARED
|
||||
TL_TRACES_TABLE 0x2003007c (NOLOAD) : { *(TL_TRACES_TABLE) } >RAM_SHARED
|
||||
TL_MAC_802_15_4_TABLE 0x20030080 (NOLOAD) : { *(TL_MAC_802_15_4_TABLE) } >RAM_SHARED
|
||||
|
||||
HCI_ACL_DATA_BUFFER 0x20030a08 (NOLOAD) : { *(HCI_ACL_DATA_BUFFER) } >RAM_SHARED
|
||||
BLE_CMD_BUFFER 0x200308fc (NOLOAD) : { *(BLE_CMD_BUFFER) } >RAM_SHARED
|
||||
BLE_SPARE_EVT_BUF 0x200301a8 (NOLOAD) : { *(BLE_SPARE_EVT_BUF) } >RAM_SHARED
|
||||
SYS_SPARE_EVT_BUF 0x200302b4 (NOLOAD) : { *(SYS_SPARE_EVT_BUF) } >RAM_SHARED
|
||||
EVT_POOL 0x200303c0 (NOLOAD) : { *(EVT_POOL) } >RAM_SHARED
|
||||
SYS_CMD_BUF 0x2003009c (NOLOAD) : { *(SYS_CMD_BUF) } >RAM_SHARED
|
||||
SYSTEM_EVT_QUEUE 0x20030b28 (NOLOAD) : { *(SYSTEM_EVT_QUEUE) } >RAM_SHARED
|
||||
EVT_QUEUE 0x20030b10 (NOLOAD) : { *(EVT_QUEUE) } >RAM_SHARED
|
||||
CS_BUFFER 0x20030b18 (NOLOAD) : { *(CS_BUFFER) } >RAM_SHARED
|
||||
TRACES_EVT_QUEUE 0x20030094 (NOLOAD) : { *(TRACES_EVT_QUEUE) } >RAM_SHARED
|
||||
FREE_BUF_QUEUE 0x2003008c (NOLOAD) : { *(FREE_BUF_QUEUE) } >RAM_SHARED
|
||||
MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED
|
||||
MB_MEM2 (NOLOAD) : { _sMB_MEM2 = . ; *(MB_MEM2) ; _eMB_MEM2 = . ; } >RAM_SHARED
|
||||
}
|
||||
|
|
68
examples/stm32wb/src/bin/tl_mbox.rs
Normal file
68
examples/stm32wb/src/bin/tl_mbox.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
#![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 embassy_time::{Duration, Timer};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
/*
|
||||
How to make this work:
|
||||
|
||||
- Obtain a NUCLEO-STM32WB55 from your preferred supplier.
|
||||
- Download and Install STM32CubeProgrammer.
|
||||
- Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from
|
||||
gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x
|
||||
- Open STM32CubeProgrammer
|
||||
- On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware.
|
||||
- Once complete, click connect to connect to the device.
|
||||
- On the left hand pane, click the RSS signal icon to open "Firmware Upgrade Services".
|
||||
- In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file
|
||||
- Select that file, the memory address, "verify download", and then "Firmware Upgrade".
|
||||
- Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the
|
||||
stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address.
|
||||
- Select that file, the memory address, "verify download", and then "Firmware Upgrade".
|
||||
- Disconnect from the device.
|
||||
- In the examples folder for stm32wb, modify the memory.x file to match your target device.
|
||||
- Run this example.
|
||||
|
||||
Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Timer::after(Duration::from_millis(500)).await;
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board
|
|||
|
||||
sdmmc = []
|
||||
chrono = ["embassy-stm32/chrono", "dep:chrono"]
|
||||
ble = []
|
||||
not-gpdma = []
|
||||
|
||||
[dependencies]
|
||||
|
@ -43,6 +44,11 @@ chrono = { version = "^0.4", default-features = false, optional = true}
|
|||
|
||||
# BEGIN TESTS
|
||||
# Generated by gen_test.py. DO NOT EDIT.
|
||||
[[bin]]
|
||||
name = "ble"
|
||||
path = "src/bin/ble.rs"
|
||||
required-features = [ "ble",]
|
||||
|
||||
[[bin]]
|
||||
name = "gpio"
|
||||
path = "src/bin/gpio.rs"
|
||||
|
|
51
tests/stm32/src/bin/ble.rs
Normal file
51
tests/stm32/src/bin/ble.rs
Normal file
|
@ -0,0 +1,51 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
// required-features: ble
|
||||
|
||||
#[path = "../example_common.rs"]
|
||||
mod example_common;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::ipcc::{Config, Ipcc};
|
||||
use embassy_stm32::tl_mbox::TlMbox;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use example_common::*;
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let p = embassy_stm32::init(config());
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Timer::after(Duration::from_millis(500)).await;
|
||||
}
|
||||
|
||||
info!("Test OK");
|
||||
cortex_m::asm::bkpt();
|
||||
}
|
Loading…
Reference in a new issue