1489: stm32/ipcc: make IPCC methods static r=xoviat a=OueslatiGhaith



1500: stm32/tests: disable sdmmc test for now r=xoviat a=xoviat



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-29 14:42:51 +00:00 committed by GitHub
commit bab03a3927
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 192 additions and 273 deletions

View File

@ -912,6 +912,16 @@ fn main() {
println!("cargo:rustc-cfg={}x{}", &chip_name[..9], &chip_name[10..11]); println!("cargo:rustc-cfg={}x{}", &chip_name[..9], &chip_name[10..11]);
} }
// ========
// stm32wb tl_mbox link sections
if chip_name.starts_with("stm32wb") {
let out_file = out_dir.join("tl_mbox.x").to_string_lossy().to_string();
fs::write(out_file, fs::read_to_string("tl_mbox.x.in").unwrap()).unwrap();
println!("cargo:rustc-link-search={}", out_dir.display());
println!("cargo:rerun-if-changed=tl_mbox.x.in");
}
// ======= // =======
// Features for targeting groups of chips // Features for targeting groups of chips

View File

@ -41,8 +41,6 @@ pub mod crc;
pub mod flash; pub mod flash;
#[cfg(all(spi_v1, rcc_f4))] #[cfg(all(spi_v1, rcc_f4))]
pub mod i2s; pub mod i2s;
#[cfg(stm32wb)]
pub mod ipcc;
pub mod pwm; pub mod pwm;
#[cfg(quadspi)] #[cfg(quadspi)]
pub mod qspi; pub mod qspi;

View File

@ -1,5 +1,3 @@
use core::mem::MaybeUninit;
use embassy_futures::block_on; use embassy_futures::block_on;
use super::cmd::CmdSerial; use super::cmd::CmdSerial;
@ -10,17 +8,17 @@ use super::{
channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE, TL_CHANNEL, channels, BleTable, BLE_CMD_BUFFER, CS_BUFFER, EVT_QUEUE, HCI_ACL_DATA_BUFFER, TL_BLE_TABLE, TL_CHANNEL,
TL_REF_TABLE, TL_REF_TABLE,
}; };
use crate::ipcc::Ipcc;
use crate::tl_mbox::cmd::CmdPacket; use crate::tl_mbox::cmd::CmdPacket;
use crate::tl_mbox::ipcc::Ipcc;
pub struct Ble; pub struct Ble;
impl Ble { impl Ble {
pub(crate) fn new(ipcc: &mut Ipcc) -> Self { pub fn enable() {
unsafe { unsafe {
LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr()); LinkedListNode::init_head(EVT_QUEUE.as_mut_ptr());
TL_BLE_TABLE = MaybeUninit::new(BleTable { TL_BLE_TABLE.as_mut_ptr().write_volatile(BleTable {
pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(), pcmd_buffer: BLE_CMD_BUFFER.as_mut_ptr().cast(),
pcs_buffer: CS_BUFFER.as_mut_ptr().cast(), pcs_buffer: CS_BUFFER.as_mut_ptr().cast(),
pevt_queue: EVT_QUEUE.as_ptr().cast(), pevt_queue: EVT_QUEUE.as_ptr().cast(),
@ -28,12 +26,10 @@ impl Ble {
}); });
} }
ipcc.c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true); Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true);
Ble
} }
pub(crate) fn evt_handler(ipcc: &mut Ipcc) { pub fn evt_handler() {
unsafe { unsafe {
let mut node_ptr = core::ptr::null_mut(); let mut node_ptr = core::ptr::null_mut();
let node_ptr_ptr: *mut _ = &mut node_ptr; let node_ptr_ptr: *mut _ = &mut node_ptr;
@ -48,10 +44,10 @@ impl Ble {
} }
} }
ipcc.c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL); Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL);
} }
pub(crate) fn send_cmd(ipcc: &mut Ipcc, buf: &[u8]) { pub fn send_cmd(buf: &[u8]) {
unsafe { unsafe {
let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer; let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer;
let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmd_serial; let pcmd_serial: *mut CmdSerial = &mut (*pcmd_buffer).cmd_serial;
@ -63,6 +59,6 @@ impl Ble {
cmd_packet.cmd_serial.ty = TlPacketType::BleCmd as u8; cmd_packet.cmd_serial.ty = TlPacketType::BleCmd as u8;
} }
ipcc.c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL); Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL);
} }
} }

View File

@ -50,7 +50,7 @@
//! //!
pub mod cpu1 { pub mod cpu1 {
use crate::ipcc::IpccChannel; use crate::tl_mbox::ipcc::IpccChannel;
// Not used currently but reserved // Not used currently but reserved
pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1; pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1;
@ -75,7 +75,7 @@ pub mod cpu1 {
} }
pub mod cpu2 { pub mod cpu2 {
use crate::ipcc::IpccChannel; use crate::tl_mbox::ipcc::IpccChannel;
pub const IPCC_BLE_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel1; pub const IPCC_BLE_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel1;
pub const IPCC_SYSTEM_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel2; pub const IPCC_SYSTEM_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel2;

View File

@ -3,7 +3,7 @@ use core::mem::MaybeUninit;
use super::cmd::{AclDataPacket, AclDataSerial}; use super::cmd::{AclDataPacket, AclDataSerial};
use super::consts::TlPacketType; use super::consts::TlPacketType;
use super::{PacketHeader, TL_EVT_HEADER_SIZE}; use super::{PacketHeader, TL_EVT_HEADER_SIZE};
use crate::tl_mbox::mm; use crate::tl_mbox::mm::MemoryManager;
/// the payload of [`Evt`] for a command status event /// the payload of [`Evt`] for a command status event
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -131,9 +131,6 @@ impl EvtBox {
impl Drop for EvtBox { impl Drop for EvtBox {
fn drop(&mut self) { fn drop(&mut self) {
use crate::ipcc::Ipcc; MemoryManager::evt_drop(self.ptr);
let mut ipcc = Ipcc::new_inner(unsafe { crate::Peripherals::steal() }.IPCC);
mm::MemoryManager::evt_drop(self.ptr, &mut ipcc);
} }
} }

View File

@ -1,6 +1,4 @@
use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; use self::sealed::Instance;
use crate::ipcc::sealed::Instance;
use crate::peripherals::IPCC; use crate::peripherals::IPCC;
use crate::rcc::sealed::RccPeripheral; use crate::rcc::sealed::RccPeripheral;
@ -22,29 +20,17 @@ pub enum IpccChannel {
Channel6 = 5, Channel6 = 5,
} }
pub(crate) mod sealed { pub mod sealed {
pub trait Instance: crate::rcc::RccPeripheral { pub trait Instance: crate::rcc::RccPeripheral {
fn regs() -> crate::pac::ipcc::Ipcc; fn regs() -> crate::pac::ipcc::Ipcc;
fn set_cpu2(enabled: bool); fn set_cpu2(enabled: bool);
} }
} }
pub struct Ipcc<'d> { pub struct Ipcc;
_peri: PeripheralRef<'d, IPCC>,
}
impl<'d> Ipcc<'d> { impl Ipcc {
pub fn new(peri: impl Peripheral<P = IPCC> + 'd, _config: Config) -> Self { pub fn enable(_config: Config) {
Self::new_inner(peri)
}
pub(crate) fn new_inner(peri: impl Peripheral<P = IPCC> + 'd) -> Self {
into_ref!(peri);
Self { _peri: peri }
}
pub fn init(&mut self) {
IPCC::enable(); IPCC::enable();
IPCC::reset(); IPCC::reset();
IPCC::set_cpu2(true); IPCC::set_cpu2(true);
@ -61,56 +47,60 @@ impl<'d> Ipcc<'d> {
} }
} }
pub fn c1_set_rx_channel(&mut self, channel: IpccChannel, enabled: bool) { pub fn c1_set_rx_channel(channel: IpccChannel, enabled: bool) {
let regs = IPCC::regs(); let regs = IPCC::regs();
// If bit is set to 1 then interrupt is disabled // If bit is set to 1 then interrupt is disabled
unsafe { regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, !enabled)) } unsafe { regs.cpu(0).mr().modify(|w| w.set_chom(channel as usize, !enabled)) }
} }
pub fn c1_get_rx_channel(&self, channel: IpccChannel) -> bool { pub fn c1_get_rx_channel(channel: IpccChannel) -> bool {
let regs = IPCC::regs(); let regs = IPCC::regs();
// If bit is set to 1 then interrupt is disabled // If bit is set to 1 then interrupt is disabled
unsafe { !regs.cpu(0).mr().read().chom(channel as usize) } unsafe { !regs.cpu(0).mr().read().chom(channel as usize) }
} }
pub fn c2_set_rx_channel(&mut self, channel: IpccChannel, enabled: bool) { #[allow(dead_code)]
pub fn c2_set_rx_channel(channel: IpccChannel, enabled: bool) {
let regs = IPCC::regs(); let regs = IPCC::regs();
// If bit is set to 1 then interrupt is disabled // If bit is set to 1 then interrupt is disabled
unsafe { regs.cpu(1).mr().modify(|w| w.set_chom(channel as usize, !enabled)) } unsafe { regs.cpu(1).mr().modify(|w| w.set_chom(channel as usize, !enabled)) }
} }
pub fn c2_get_rx_channel(&self, channel: IpccChannel) -> bool { #[allow(dead_code)]
pub fn c2_get_rx_channel(channel: IpccChannel) -> bool {
let regs = IPCC::regs(); let regs = IPCC::regs();
// If bit is set to 1 then interrupt is disabled // If bit is set to 1 then interrupt is disabled
unsafe { !regs.cpu(1).mr().read().chom(channel as usize) } unsafe { !regs.cpu(1).mr().read().chom(channel as usize) }
} }
pub fn c1_set_tx_channel(&mut self, channel: IpccChannel, enabled: bool) { pub fn c1_set_tx_channel(channel: IpccChannel, enabled: bool) {
let regs = IPCC::regs(); let regs = IPCC::regs();
// If bit is set to 1 then interrupt is disabled // If bit is set to 1 then interrupt is disabled
unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) } unsafe { regs.cpu(0).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) }
} }
pub fn c1_get_tx_channel(&self, channel: IpccChannel) -> bool { pub fn c1_get_tx_channel(channel: IpccChannel) -> bool {
let regs = IPCC::regs(); let regs = IPCC::regs();
// If bit is set to 1 then interrupt is disabled // If bit is set to 1 then interrupt is disabled
unsafe { !regs.cpu(0).mr().read().chfm(channel as usize) } unsafe { !regs.cpu(0).mr().read().chfm(channel as usize) }
} }
pub fn c2_set_tx_channel(&mut self, channel: IpccChannel, enabled: bool) { #[allow(dead_code)]
pub fn c2_set_tx_channel(channel: IpccChannel, enabled: bool) {
let regs = IPCC::regs(); let regs = IPCC::regs();
// If bit is set to 1 then interrupt is disabled // If bit is set to 1 then interrupt is disabled
unsafe { regs.cpu(1).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) } unsafe { regs.cpu(1).mr().modify(|w| w.set_chfm(channel as usize, !enabled)) }
} }
pub fn c2_get_tx_channel(&self, channel: IpccChannel) -> bool { #[allow(dead_code)]
pub fn c2_get_tx_channel(channel: IpccChannel) -> bool {
let regs = IPCC::regs(); let regs = IPCC::regs();
// If bit is set to 1 then interrupt is disabled // If bit is set to 1 then interrupt is disabled
@ -118,53 +108,51 @@ impl<'d> Ipcc<'d> {
} }
/// clears IPCC receive channel status for CPU1 /// clears IPCC receive channel status for CPU1
pub fn c1_clear_flag_channel(&mut self, channel: IpccChannel) { pub fn c1_clear_flag_channel(channel: IpccChannel) {
let regs = IPCC::regs(); let regs = IPCC::regs();
unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) } unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) }
} }
#[allow(dead_code)]
/// clears IPCC receive channel status for CPU2 /// clears IPCC receive channel status for CPU2
pub fn c2_clear_flag_channel(&mut self, channel: IpccChannel) { pub fn c2_clear_flag_channel(channel: IpccChannel) {
let regs = IPCC::regs(); let regs = IPCC::regs();
unsafe { regs.cpu(1).scr().write(|w| w.set_chc(channel as usize, true)) } unsafe { regs.cpu(1).scr().write(|w| w.set_chc(channel as usize, true)) }
} }
pub fn c1_set_flag_channel(&mut self, channel: IpccChannel) { pub fn c1_set_flag_channel(channel: IpccChannel) {
let regs = IPCC::regs(); let regs = IPCC::regs();
unsafe { regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)) } unsafe { regs.cpu(0).scr().write(|w| w.set_chs(channel as usize, true)) }
} }
pub fn c2_set_flag_channel(&mut self, channel: IpccChannel) { #[allow(dead_code)]
pub fn c2_set_flag_channel(channel: IpccChannel) {
let regs = IPCC::regs(); let regs = IPCC::regs();
unsafe { regs.cpu(1).scr().write(|w| w.set_chs(channel as usize, true)) } unsafe { regs.cpu(1).scr().write(|w| w.set_chs(channel as usize, true)) }
} }
pub fn c1_is_active_flag(&self, channel: IpccChannel) -> bool { pub fn c1_is_active_flag(channel: IpccChannel) -> bool {
let regs = IPCC::regs(); let regs = IPCC::regs();
unsafe { regs.cpu(0).sr().read().chf(channel as usize) } unsafe { regs.cpu(0).sr().read().chf(channel as usize) }
} }
pub fn c2_is_active_flag(&self, channel: IpccChannel) -> bool { pub fn c2_is_active_flag(channel: IpccChannel) -> bool {
let regs = IPCC::regs(); let regs = IPCC::regs();
unsafe { regs.cpu(1).sr().read().chf(channel as usize) } unsafe { regs.cpu(1).sr().read().chf(channel as usize) }
} }
pub fn is_tx_pending(&self, channel: IpccChannel) -> bool { pub fn is_tx_pending(channel: IpccChannel) -> bool {
!self.c1_is_active_flag(channel) && self.c1_get_tx_channel(channel) !Self::c1_is_active_flag(channel) && Self::c1_get_tx_channel(channel)
} }
pub fn is_rx_pending(&self, channel: IpccChannel) -> bool { pub fn is_rx_pending(channel: IpccChannel) -> bool {
self.c2_is_active_flag(channel) && self.c1_get_rx_channel(channel) Self::c2_is_active_flag(channel) && Self::c1_get_rx_channel(channel)
}
pub fn as_mut_ptr(&self) -> *mut Self {
unsafe { &mut core::ptr::read(self) as *mut _ }
} }
} }

View File

@ -1,22 +1,20 @@
use core::mem::MaybeUninit;
use super::evt::EvtPacket; use super::evt::EvtPacket;
use super::unsafe_linked_list::LinkedListNode; use super::unsafe_linked_list::LinkedListNode;
use super::{ use super::{
channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUFF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE, channels, MemManagerTable, BLE_SPARE_EVT_BUF, EVT_POOL, FREE_BUFF_QUEUE, LOCAL_FREE_BUF_QUEUE, POOL_SIZE,
SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, TL_REF_TABLE, SYS_SPARE_EVT_BUF, TL_MEM_MANAGER_TABLE, TL_REF_TABLE,
}; };
use crate::ipcc::Ipcc; use crate::tl_mbox::ipcc::Ipcc;
pub struct MemoryManager; pub struct MemoryManager;
impl MemoryManager { impl MemoryManager {
pub fn new() -> Self { pub fn enable() {
unsafe { unsafe {
LinkedListNode::init_head(FREE_BUFF_QUEUE.as_mut_ptr()); LinkedListNode::init_head(FREE_BUFF_QUEUE.as_mut_ptr());
LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr()); LinkedListNode::init_head(LOCAL_FREE_BUF_QUEUE.as_mut_ptr());
TL_MEM_MANAGER_TABLE = MaybeUninit::new(MemManagerTable { TL_MEM_MANAGER_TABLE.as_mut_ptr().write_volatile(MemManagerTable {
spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(), spare_ble_buffer: BLE_SPARE_EVT_BUF.as_ptr().cast(),
spare_sys_buffer: SYS_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: EVT_POOL.as_ptr().cast(),
@ -26,31 +24,29 @@ impl MemoryManager {
traces_pool_size: 0, traces_pool_size: 0,
}); });
} }
MemoryManager
} }
pub fn evt_handler(ipcc: &mut Ipcc) { pub fn evt_handler() {
ipcc.c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false); Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false);
Self::send_free_buf(); Self::send_free_buf();
ipcc.c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL);
} }
pub fn evt_drop(evt: *mut EvtPacket, ipcc: &mut Ipcc) { pub fn evt_drop(evt: *mut EvtPacket) {
unsafe { unsafe {
let list_node = evt.cast(); let list_node = evt.cast();
LinkedListNode::remove_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node); LinkedListNode::remove_tail(LOCAL_FREE_BUF_QUEUE.as_mut_ptr(), list_node);
} }
let channel_is_busy = ipcc.c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); let channel_is_busy = Ipcc::c1_is_active_flag(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL);
// postpone event buffer freeing to IPCC interrupt handler // postpone event buffer freeing to IPCC interrupt handler
if channel_is_busy { if channel_is_busy {
ipcc.c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true); Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, true);
} else { } else {
Self::send_free_buf(); Self::send_free_buf();
ipcc.c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL); Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL);
} }
} }

View File

@ -1,6 +1,9 @@
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
use atomic_polyfill::{compiler_fence, Ordering};
use bit_field::BitField; use bit_field::BitField;
use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Channel; use embassy_sync::channel::Channel;
@ -12,13 +15,16 @@ use self::shci::{shci_ble_init, ShciBleInitCmdParam};
use self::sys::Sys; use self::sys::Sys;
use self::unsafe_linked_list::LinkedListNode; use self::unsafe_linked_list::LinkedListNode;
use crate::interrupt; use crate::interrupt;
use crate::ipcc::Ipcc; use crate::peripherals::IPCC;
pub use crate::tl_mbox::ipcc::Config;
use crate::tl_mbox::ipcc::Ipcc;
mod ble; mod ble;
mod channels; mod channels;
mod cmd; mod cmd;
mod consts; mod consts;
mod evt; mod evt;
mod ipcc;
mod mm; mod mm;
mod shci; mod shci;
mod sys; mod sys;
@ -58,13 +64,34 @@ pub struct FusInfoTable {
pub struct ReceiveInterruptHandler {} pub struct ReceiveInterruptHandler {}
impl interrupt::Handler<interrupt::IPCC_C1_RX> for ReceiveInterruptHandler { impl interrupt::Handler<interrupt::IPCC_C1_RX> for ReceiveInterruptHandler {
unsafe fn on_interrupt() {} unsafe fn on_interrupt() {
// info!("ipcc rx interrupt");
if Ipcc::is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) {
sys::Sys::evt_handler();
} else if Ipcc::is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) {
ble::Ble::evt_handler();
} else {
todo!()
}
}
} }
pub struct TransmitInterruptHandler {} pub struct TransmitInterruptHandler {}
impl interrupt::Handler<interrupt::IPCC_C1_TX> for TransmitInterruptHandler { impl interrupt::Handler<interrupt::IPCC_C1_TX> for TransmitInterruptHandler {
unsafe fn on_interrupt() {} unsafe fn on_interrupt() {
// info!("ipcc tx interrupt");
if Ipcc::is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) {
// TODO: handle this case
let _ = sys::Sys::cmd_evt_handler();
} else if Ipcc::is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) {
mm::MemoryManager::evt_handler();
} else {
todo!()
}
}
} }
/// # Version /// # Version
@ -289,21 +316,24 @@ static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251
// TODO: get a better size, this is a placeholder // TODO: get a better size, this is a placeholder
pub(crate) static TL_CHANNEL: Channel<CriticalSectionRawMutex, EvtBox, 5> = Channel::new(); pub(crate) static TL_CHANNEL: Channel<CriticalSectionRawMutex, EvtBox, 5> = Channel::new();
pub struct TlMbox { pub struct TlMbox<'d> {
_sys: Sys, _ipcc: PeripheralRef<'d, IPCC>,
_ble: Ble,
_mm: MemoryManager,
} }
impl TlMbox { impl<'d> TlMbox<'d> {
/// initializes low-level transport between CPU1 and BLE stack on CPU2 /// initializes low-level transport between CPU1 and BLE stack on CPU2
pub fn init( pub fn new(
ipcc: &mut Ipcc, ipcc: impl Peripheral<P = IPCC> + 'd,
_irqs: impl interrupt::Binding<interrupt::IPCC_C1_RX, ReceiveInterruptHandler> _irqs: impl interrupt::Binding<interrupt::IPCC_C1_RX, ReceiveInterruptHandler>
+ interrupt::Binding<interrupt::IPCC_C1_TX, TransmitInterruptHandler>, + interrupt::Binding<interrupt::IPCC_C1_TX, TransmitInterruptHandler>,
) -> TlMbox { config: Config,
) -> Self {
into_ref!(ipcc);
unsafe { unsafe {
TL_REF_TABLE = MaybeUninit::new(RefTable { compiler_fence(Ordering::AcqRel);
TL_REF_TABLE.as_mut_ptr().write_volatile(RefTable {
device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(), device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(),
ble_table: TL_BLE_TABLE.as_ptr(), ble_table: TL_BLE_TABLE.as_ptr(),
thread_table: TL_THREAD_TABLE.as_ptr(), thread_table: TL_THREAD_TABLE.as_ptr(),
@ -316,6 +346,10 @@ impl TlMbox {
ble_lld_table: TL_BLE_LLD_TABLE.as_ptr(), ble_lld_table: TL_BLE_LLD_TABLE.as_ptr(),
}); });
// info!("TL_REF_TABLE addr: {:x}", TL_REF_TABLE.as_ptr() as usize);
compiler_fence(Ordering::AcqRel);
TL_SYS_TABLE = MaybeUninit::zeroed(); TL_SYS_TABLE = MaybeUninit::zeroed();
TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed(); TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed();
TL_BLE_TABLE = MaybeUninit::zeroed(); TL_BLE_TABLE = MaybeUninit::zeroed();
@ -334,33 +368,24 @@ impl TlMbox {
CS_BUFFER = MaybeUninit::zeroed(); CS_BUFFER = MaybeUninit::zeroed();
BLE_CMD_BUFFER = MaybeUninit::zeroed(); BLE_CMD_BUFFER = MaybeUninit::zeroed();
HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed(); HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed();
compiler_fence(Ordering::AcqRel);
} }
ipcc.init(); Ipcc::enable(config);
let _sys = Sys::new(ipcc); Sys::enable();
let _ble = Ble::new(ipcc); Ble::enable();
let _mm = MemoryManager::new(); MemoryManager::enable();
// rx_irq.disable(); // enable interrupts
// tx_irq.disable(); unsafe { crate::interrupt::IPCC_C1_RX::steal() }.unpend();
// unsafe { crate::interrupt::IPCC_C1_TX::steal() }.unpend();
// rx_irq.set_handler_context(ipcc.as_mut_ptr() as *mut ());
// tx_irq.set_handler_context(ipcc.as_mut_ptr() as *mut ());
//
// rx_irq.set_handler(|ipcc| {
// let ipcc: &mut Ipcc = unsafe { &mut *ipcc.cast() };
// Self::interrupt_ipcc_rx_handler(ipcc);
// });
// tx_irq.set_handler(|ipcc| {
// let ipcc: &mut Ipcc = unsafe { &mut *ipcc.cast() };
// Self::interrupt_ipcc_tx_handler(ipcc);
// });
//
// rx_irq.enable();
// tx_irq.enable();
TlMbox { _sys, _ble, _mm } unsafe { crate::interrupt::IPCC_C1_RX::steal() }.enable();
unsafe { crate::interrupt::IPCC_C1_TX::steal() }.enable();
Self { _ipcc: ipcc }
} }
pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> { pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> {
@ -374,42 +399,19 @@ impl TlMbox {
} }
} }
pub fn shci_ble_init(&self, ipcc: &mut Ipcc, param: ShciBleInitCmdParam) { pub fn shci_ble_init(&self, param: ShciBleInitCmdParam) {
shci_ble_init(ipcc, param); shci_ble_init(param);
} }
pub fn send_ble_cmd(&self, ipcc: &mut Ipcc, buf: &[u8]) { pub fn send_ble_cmd(&self, buf: &[u8]) {
ble::Ble::send_cmd(ipcc, buf); ble::Ble::send_cmd(buf);
} }
// pub fn send_sys_cmd(&self, ipcc: &mut Ipcc, buf: &[u8]) { // pub fn send_sys_cmd(&self, buf: &[u8]) {
// sys::Sys::send_cmd(ipcc, buf); // sys::Sys::send_cmd(buf);
// } // }
pub async fn read(&self) -> EvtBox { pub async fn read(&self) -> EvtBox {
TL_CHANNEL.recv().await TL_CHANNEL.recv().await
} }
#[allow(dead_code)]
fn interrupt_ipcc_rx_handler(ipcc: &mut Ipcc) {
if ipcc.is_rx_pending(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL) {
sys::Sys::evt_handler(ipcc);
} else if ipcc.is_rx_pending(channels::cpu2::IPCC_BLE_EVENT_CHANNEL) {
ble::Ble::evt_handler(ipcc);
} else {
todo!()
}
}
#[allow(dead_code)]
fn interrupt_ipcc_tx_handler(ipcc: &mut Ipcc) {
if ipcc.is_tx_pending(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL) {
// TODO: handle this case
let _ = sys::Sys::cmd_evt_handler(ipcc);
} else if ipcc.is_tx_pending(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL) {
mm::MemoryManager::evt_handler(ipcc);
} else {
todo!()
}
}
} }

View File

@ -3,7 +3,7 @@
use super::cmd::CmdPacket; use super::cmd::CmdPacket;
use super::consts::TlPacketType; use super::consts::TlPacketType;
use super::{channels, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE}; use super::{channels, TL_CS_EVT_SIZE, TL_EVT_HEADER_SIZE, TL_PACKET_HEADER_SIZE, TL_SYS_TABLE};
use crate::ipcc::Ipcc; use crate::tl_mbox::ipcc::Ipcc;
const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66; const SCHI_OPCODE_BLE_INIT: u16 = 0xfc66;
pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE; pub const TL_BLE_EVT_CS_PACKET_SIZE: usize = TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE;
@ -76,7 +76,7 @@ pub struct ShciBleInitCmdPacket {
param: ShciBleInitCmdParam, param: ShciBleInitCmdParam,
} }
pub fn shci_ble_init(ipcc: &mut Ipcc, param: ShciBleInitCmdParam) { pub fn shci_ble_init(param: ShciBleInitCmdParam) {
let mut packet = ShciBleInitCmdPacket { let mut packet = ShciBleInitCmdPacket {
header: ShciHeader::default(), header: ShciHeader::default(),
param, param,
@ -95,7 +95,7 @@ pub fn shci_ble_init(ipcc: &mut Ipcc, param: ShciBleInitCmdParam) {
cmd_buf.cmd_serial.ty = TlPacketType::SysCmd as u8; cmd_buf.cmd_serial.ty = TlPacketType::SysCmd as u8;
ipcc.c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL);
ipcc.c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true);
} }
} }

View File

@ -1,5 +1,3 @@
use core::mem::MaybeUninit;
use embassy_futures::block_on; use embassy_futures::block_on;
use super::cmd::{CmdPacket, CmdSerial}; use super::cmd::{CmdPacket, CmdSerial};
@ -7,27 +5,25 @@ use super::consts::TlPacketType;
use super::evt::{CcEvt, EvtBox, EvtSerial}; use super::evt::{CcEvt, EvtBox, EvtSerial};
use super::unsafe_linked_list::LinkedListNode; use super::unsafe_linked_list::LinkedListNode;
use super::{channels, SysTable, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_CHANNEL, TL_REF_TABLE, TL_SYS_TABLE}; use super::{channels, SysTable, SYSTEM_EVT_QUEUE, SYS_CMD_BUF, TL_CHANNEL, TL_REF_TABLE, TL_SYS_TABLE};
use crate::ipcc::Ipcc; use crate::tl_mbox::ipcc::Ipcc;
pub struct Sys; pub struct Sys;
impl Sys { impl Sys {
pub(crate) fn new(ipcc: &mut Ipcc) -> Self { pub fn enable() {
unsafe { unsafe {
LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr()); LinkedListNode::init_head(SYSTEM_EVT_QUEUE.as_mut_ptr());
TL_SYS_TABLE = MaybeUninit::new(SysTable { TL_SYS_TABLE.as_mut_ptr().write_volatile(SysTable {
pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(), pcmd_buffer: SYS_CMD_BUF.as_mut_ptr(),
sys_queue: SYSTEM_EVT_QUEUE.as_ptr(), sys_queue: SYSTEM_EVT_QUEUE.as_ptr(),
}); });
} }
ipcc.c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true); Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true);
Sys
} }
pub(crate) fn evt_handler(ipcc: &mut Ipcc) { pub fn evt_handler() {
unsafe { unsafe {
let mut node_ptr = core::ptr::null_mut(); let mut node_ptr = core::ptr::null_mut();
let node_ptr_ptr: *mut _ = &mut node_ptr; let node_ptr_ptr: *mut _ = &mut node_ptr;
@ -43,11 +39,11 @@ impl Sys {
} }
} }
ipcc.c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL); Ipcc::c1_clear_flag_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL);
} }
pub(crate) fn cmd_evt_handler(ipcc: &mut Ipcc) -> CcEvt { pub fn cmd_evt_handler() -> CcEvt {
ipcc.c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, false); Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, false);
// ST's command response data structure is really convoluted. // ST's command response data structure is really convoluted.
// //
@ -68,11 +64,11 @@ impl Sys {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) fn send_cmd(ipcc: &mut Ipcc, buf: &[u8]) { pub fn send_cmd(buf: &[u8]) {
unsafe { unsafe {
// TODO: check this // TODO: check this
let cmd_buffer = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer; let cmd_buffer = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer;
let cmd_serial: *mut CmdSerial = &mut (*cmd_buffer).cmd_serial; let cmd_serial: *mut CmdSerial = &mut cmd_buffer.cmd_serial;
let cmd_serial_buf = cmd_serial.cast(); let cmd_serial_buf = cmd_serial.cast();
core::ptr::copy(buf.as_ptr(), cmd_serial_buf, buf.len()); core::ptr::copy(buf.as_ptr(), cmd_serial_buf, buf.len());
@ -80,8 +76,8 @@ impl Sys {
let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer; let cmd_packet = &mut *(*TL_REF_TABLE.assume_init().sys_table).pcmd_buffer;
cmd_packet.cmd_serial.ty = TlPacketType::SysCmd as u8; cmd_packet.cmd_serial.ty = TlPacketType::SysCmd as u8;
ipcc.c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL); Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL);
ipcc.c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true); Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true);
} }
} }
} }

View File

@ -1,21 +1,13 @@
/*
Memory size for STM32WB55xG with 512K FLASH
*/
MEMORY MEMORY
{ {
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
RAM (xrw) : ORIGIN = 0x20000008, LENGTH = 0x2FFF8
RAM_SHARED (xrw) : ORIGIN = 0x20030000, LENGTH = 10K RAM_SHARED (xrw) : ORIGIN = 0x20030000, LENGTH = 10K
} }
/* Place stack at the end of SRAM1 */
_stack_start = ORIGIN(RAM) + LENGTH(RAM);
/* /*
* Scatter the mailbox interface memory sections in shared memory * Scatter the mailbox interface memory sections in shared memory
*/ */
SECTIONS { SECTIONS
{
TL_REF_TABLE (NOLOAD) : { *(TL_REF_TABLE) } >RAM_SHARED TL_REF_TABLE (NOLOAD) : { *(TL_REF_TABLE) } >RAM_SHARED
MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED

View File

@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } 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-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-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", "stm32wb55rg", "time-driver-any", "exti"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti"] }
defmt = "0.3" defmt = "0.3"
defmt-rtt = "0.4" defmt-rtt = "0.4"

View File

@ -1,35 +1,11 @@
//! This build script copies the `memory.x` file from the crate root into use std::error::Error;
//! a directory where the linker can always find it at build time.
//! For many projects this is optional, as the linker always searches the
//! project root directory -- wherever `Cargo.toml` is. However, if you
//! are using a workspace or have a more complicated build setup, this
//! build script becomes required. Additionally, by requesting that
//! Cargo re-run the build script whenever `memory.x` is changed,
//! updating `memory.x` ensures a rebuild of the application with the
//! new memory settings.
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
fn main() {
// Put `memory.x` in our output directory and ensure it's
// on the linker search path.
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
File::create(out.join("memory.x"))
.unwrap()
.write_all(include_bytes!("memory.x"))
.unwrap();
println!("cargo:rustc-link-search={}", out.display());
// By default, Cargo will re-run a build script whenever
// any file in the project changes. By specifying `memory.x`
// here, we ensure the build script is only re-run when
// `memory.x` is changed.
println!("cargo:rerun-if-changed=memory.x");
fn main() -> Result<(), Box<dyn Error>> {
println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=--nmagic");
println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tlink.x");
println!("cargo:rerun-if-changed=link.x");
println!("cargo:rustc-link-arg-bins=-Ttl_mbox.x");
println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
Ok(())
} }

View File

@ -1,35 +0,0 @@
/*
The size of this file must be exactly the same as in other memory_xx.x files.
Memory size for STM32WB55xC with 256K FLASH
*/
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
RAM_SHARED (xrw) : ORIGIN = 0x20030000, LENGTH = 10K
}
/*
Memory size for STM32WB55xG 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);
/*
* Scatter the mailbox interface memory sections in shared memory
*/
SECTIONS {
TL_REF_TABLE (NOLOAD) : { *(TL_REF_TABLE) } >RAM_SHARED
MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED
MB_MEM2 (NOLOAD) : { _sMB_MEM2 = . ; *(MB_MEM2) ; _eMB_MEM2 = . ; } >RAM_SHARED
}

View File

@ -4,8 +4,7 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::ipcc::{Config, Ipcc}; use embassy_stm32::tl_mbox::{Config, TlMbox};
use embassy_stm32::tl_mbox::TlMbox;
use embassy_stm32::{bind_interrupts, tl_mbox}; use embassy_stm32::{bind_interrupts, tl_mbox};
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@ -45,14 +44,12 @@ async fn main(_spawner: Spawner) {
info!("Hello World!"); info!("Hello World!");
let config = Config::default(); let config = Config::default();
let mut ipcc = Ipcc::new(p.IPCC, config); let mbox = TlMbox::new(p.IPCC, Irqs, config);
let mbox = TlMbox::init(&mut ipcc, Irqs);
loop { loop {
let wireless_fw_info = mbox.wireless_fw_info(); let wireless_fw_info = mbox.wireless_fw_info();
match wireless_fw_info { match wireless_fw_info {
None => error!("not yet initialized"), None => info!("not yet initialized"),
Some(fw_info) => { Some(fw_info) => {
let version_major = fw_info.version_major(); let version_major = fw_info.version_major();
let version_minor = fw_info.version_minor(); let version_minor = fw_info.version_minor();
@ -70,6 +67,9 @@ async fn main(_spawner: Spawner) {
} }
} }
Timer::after(Duration::from_millis(500)).await; Timer::after(Duration::from_millis(50)).await;
} }
info!("Test OK");
cortex_m::asm::bkpt();
} }

View File

@ -4,8 +4,7 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::ipcc::{Config, Ipcc}; use embassy_stm32::tl_mbox::{Config, TlMbox};
use embassy_stm32::tl_mbox::TlMbox;
use embassy_stm32::{bind_interrupts, tl_mbox}; use embassy_stm32::{bind_interrupts, tl_mbox};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@ -44,12 +43,7 @@ async fn main(_spawner: Spawner) {
info!("Hello World!"); info!("Hello World!");
let config = Config::default(); let config = Config::default();
let mut ipcc = Ipcc::new(p.IPCC, config); let mbox = TlMbox::new(p.IPCC, Irqs, config);
let mbox = TlMbox::init(&mut ipcc, Irqs);
// initialize ble stack, does not return a response
mbox.shci_ble_init(&mut ipcc, Default::default());
info!("waiting for coprocessor to boot"); info!("waiting for coprocessor to boot");
let event_box = mbox.read().await; let event_box = mbox.read().await;
@ -74,10 +68,11 @@ async fn main(_spawner: Spawner) {
); );
} }
mbox.shci_ble_init(&mut ipcc, Default::default()); // initialize ble stack, does not return a response
mbox.shci_ble_init(Default::default());
info!("resetting BLE"); info!("resetting BLE");
mbox.send_ble_cmd(&mut ipcc, &[0x01, 0x03, 0x0c, 0x00, 0x00]); mbox.send_ble_cmd(&[0x01, 0x03, 0x0c, 0x00, 0x00]);
let event_box = mbox.read().await; let event_box = mbox.read().await;
@ -92,8 +87,12 @@ async fn main(_spawner: Spawner) {
info!( info!(
"==> kind: {:#04x}, code: {:#04x}, payload_length: {}, payload: {:#04x}", "==> kind: {:#04x}, code: {:#04x}, payload_length: {}, payload: {:#04x}",
kind, code, payload_len, payload kind,
code,
payload_len,
payload[3..]
); );
loop {} info!("Test OK");
cortex_m::asm::bkpt();
} }

View File

@ -7,12 +7,12 @@ autobins = false
[features] [features]
stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill
stm32f429zi = ["embassy-stm32/stm32f429zi", "sdmmc", "chrono", "not-gpdma"] # Nucleo stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "not-gpdma"] # Nucleo "sdmmc"
stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo
stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo
stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo
stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo
stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma"] # Nucleo stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble"] # Nucleo
stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo
stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board
@ -45,8 +45,8 @@ chrono = { version = "^0.4", default-features = false, optional = true}
# BEGIN TESTS # BEGIN TESTS
# Generated by gen_test.py. DO NOT EDIT. # Generated by gen_test.py. DO NOT EDIT.
[[bin]] [[bin]]
name = "ble" name = "tl_mbox"
path = "src/bin/ble.rs" path = "src/bin/tl_mbox.rs"
required-features = [ "ble",] required-features = [ "ble",]
[[bin]] [[bin]]

View File

@ -9,17 +9,22 @@ fn main() -> Result<(), Box<dyn Error>> {
println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=--nmagic");
// too little RAM to run from RAM. // too little RAM to run from RAM.
if cfg!(any(feature = "stm32f103c8", feature = "stm32c031c6")) { if cfg!(any(
feature = "stm32f103c8",
feature = "stm32c031c6",
feature = "stm32wb55rg"
)) {
println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tlink.x");
println!("cargo:rerun-if-changed=link.x"); println!("cargo:rerun-if-changed=link.x");
} else if cfg!(feature = "stm32wb55rg") {
println!("cargo:rustc-link-arg-bins=-Tlink.x");
fs::write(out.join("memory.x"), include_bytes!("memory_ble.x")).unwrap();
} else { } else {
println!("cargo:rustc-link-arg-bins=-Tlink_ram.x"); println!("cargo:rustc-link-arg-bins=-Tlink_ram.x");
println!("cargo:rerun-if-changed=link_ram.x"); println!("cargo:rerun-if-changed=link_ram.x");
} }
if cfg!(feature = "stm32wb55rg") {
println!("cargo:rustc-link-arg-bins=-Ttl_mbox.x");
}
println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
Ok(()) Ok(())

View File

@ -7,24 +7,23 @@
#[path = "../example_common.rs"] #[path = "../example_common.rs"]
mod example_common; mod example_common;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_stm32::interrupt; use embassy_stm32::tl_mbox::{Config, TlMbox};
use embassy_stm32::ipcc::{Config, Ipcc}; use embassy_stm32::{bind_interrupts, tl_mbox};
use embassy_stm32::tl_mbox::TlMbox;
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use example_common::*; use example_common::*;
bind_interrupts!(struct Irqs{
IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler;
IPCC_C1_TX => tl_mbox::TransmitInterruptHandler;
});
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let p = embassy_stm32::init(config()); let p = embassy_stm32::init(config());
info!("Hello World!"); info!("Hello World!");
let config = Config::default(); let config = Config::default();
let mut ipcc = Ipcc::new(p.IPCC, config); let mbox = TlMbox::new(p.IPCC, Irqs, config);
let rx_irq = interrupt::take!(IPCC_C1_RX);
let tx_irq = interrupt::take!(IPCC_C1_TX);
let mbox = TlMbox::init(&mut ipcc, rx_irq, tx_irq);
loop { loop {
let wireless_fw_info = mbox.wireless_fw_info(); let wireless_fw_info = mbox.wireless_fw_info();