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:
bors[bot] 2023-05-11 22:48:55 +00:00 committed by GitHub
commit 7f96359804
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 830 additions and 22 deletions

3
.vscode/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.cortex-debug.*.json
launch.json
tasks.json

View File

@ -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" ]

View File

@ -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"))]

View 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
}
}

View 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;
}

View 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,
}

View 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,
}

View 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
}
}

View 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
}
}
}

View 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
}
}

View 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;
});
}

View File

@ -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"

View File

@ -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"

View File

@ -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
}

View 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;
}
}

View File

@ -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"

View 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();
}