diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index b766f073..730c78f5 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -912,6 +912,16 @@ fn main() {
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
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index c9df5c1b..b9d7a15c 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -41,8 +41,6 @@ pub mod crc;
pub mod flash;
#[cfg(all(spi_v1, rcc_f4))]
pub mod i2s;
-#[cfg(stm32wb)]
-pub mod ipcc;
pub mod pwm;
#[cfg(quadspi)]
pub mod qspi;
diff --git a/embassy-stm32/src/tl_mbox/ble.rs b/embassy-stm32/src/tl_mbox/ble.rs
index d8bf14d4..06237799 100644
--- a/embassy-stm32/src/tl_mbox/ble.rs
+++ b/embassy-stm32/src/tl_mbox/ble.rs
@@ -1,5 +1,3 @@
-use core::mem::MaybeUninit;
-
use embassy_futures::block_on;
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,
TL_REF_TABLE,
};
-use crate::ipcc::Ipcc;
use crate::tl_mbox::cmd::CmdPacket;
+use crate::tl_mbox::ipcc::Ipcc;
pub struct Ble;
impl Ble {
- pub(crate) fn new(ipcc: &mut Ipcc) -> Self {
+ pub fn enable() {
unsafe {
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(),
pcs_buffer: CS_BUFFER.as_mut_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);
-
- Ble
+ Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_BLE_EVENT_CHANNEL, true);
}
- pub(crate) fn evt_handler(ipcc: &mut Ipcc) {
+ pub fn evt_handler() {
unsafe {
let mut node_ptr = core::ptr::null_mut();
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 {
let pcmd_buffer: *mut CmdPacket = (*TL_REF_TABLE.assume_init().ble_table).pcmd_buffer;
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;
}
- ipcc.c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL);
+ Ipcc::c1_set_flag_channel(channels::cpu1::IPCC_BLE_CMD_CHANNEL);
}
}
diff --git a/embassy-stm32/src/tl_mbox/channels.rs b/embassy-stm32/src/tl_mbox/channels.rs
index aaa6ce17..25a065ba 100644
--- a/embassy-stm32/src/tl_mbox/channels.rs
+++ b/embassy-stm32/src/tl_mbox/channels.rs
@@ -50,7 +50,7 @@
//!
pub mod cpu1 {
- use crate::ipcc::IpccChannel;
+ use crate::tl_mbox::ipcc::IpccChannel;
// Not used currently but reserved
pub const IPCC_BLE_CMD_CHANNEL: IpccChannel = IpccChannel::Channel1;
@@ -75,7 +75,7 @@ pub mod cpu1 {
}
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_SYSTEM_EVENT_CHANNEL: IpccChannel = IpccChannel::Channel2;
diff --git a/embassy-stm32/src/tl_mbox/evt.rs b/embassy-stm32/src/tl_mbox/evt.rs
index 770133f2..47a8b72f 100644
--- a/embassy-stm32/src/tl_mbox/evt.rs
+++ b/embassy-stm32/src/tl_mbox/evt.rs
@@ -3,7 +3,7 @@ use core::mem::MaybeUninit;
use super::cmd::{AclDataPacket, AclDataSerial};
use super::consts::TlPacketType;
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
#[derive(Copy, Clone)]
@@ -131,9 +131,6 @@ impl EvtBox {
impl Drop for EvtBox {
fn drop(&mut self) {
- use crate::ipcc::Ipcc;
-
- let mut ipcc = Ipcc::new_inner(unsafe { crate::Peripherals::steal() }.IPCC);
- mm::MemoryManager::evt_drop(self.ptr, &mut ipcc);
+ MemoryManager::evt_drop(self.ptr);
}
}
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/tl_mbox/ipcc.rs
similarity index 65%
rename from embassy-stm32/src/ipcc.rs
rename to embassy-stm32/src/tl_mbox/ipcc.rs
index 2b9caf8e..d1ac731e 100644
--- a/embassy-stm32/src/ipcc.rs
+++ b/embassy-stm32/src/tl_mbox/ipcc.rs
@@ -1,6 +1,4 @@
-use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
-
-use crate::ipcc::sealed::Instance;
+use self::sealed::Instance;
use crate::peripherals::IPCC;
use crate::rcc::sealed::RccPeripheral;
@@ -22,29 +20,17 @@ pub enum IpccChannel {
Channel6 = 5,
}
-pub(crate) mod sealed {
+pub mod sealed {
pub trait Instance: crate::rcc::RccPeripheral {
fn regs() -> crate::pac::ipcc::Ipcc;
fn set_cpu2(enabled: bool);
}
}
-pub struct Ipcc<'d> {
- _peri: PeripheralRef<'d, IPCC>,
-}
+pub struct Ipcc;
-impl<'d> Ipcc<'d> {
- pub fn new(peri: impl Peripheral
+ 'd, _config: Config) -> Self {
- Self::new_inner(peri)
- }
-
- pub(crate) fn new_inner(peri: impl Peripheral
+ 'd) -> Self {
- into_ref!(peri);
-
- Self { _peri: peri }
- }
-
- pub fn init(&mut self) {
+impl Ipcc {
+ pub fn enable(_config: Config) {
IPCC::enable();
IPCC::reset();
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();
// If bit is set to 1 then interrupt is disabled
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();
// If bit is set to 1 then interrupt is disabled
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();
// If bit is set to 1 then interrupt is disabled
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();
// If bit is set to 1 then interrupt is disabled
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();
// If bit is set to 1 then interrupt is disabled
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();
// If bit is set to 1 then interrupt is disabled
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();
// If bit is set to 1 then interrupt is disabled
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();
// 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
- pub fn c1_clear_flag_channel(&mut self, channel: IpccChannel) {
+ pub fn c1_clear_flag_channel(channel: IpccChannel) {
let regs = IPCC::regs();
unsafe { regs.cpu(0).scr().write(|w| w.set_chc(channel as usize, true)) }
}
+ #[allow(dead_code)]
/// 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();
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();
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();
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();
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();
unsafe { regs.cpu(1).sr().read().chf(channel as usize) }
}
- pub fn is_tx_pending(&self, channel: IpccChannel) -> bool {
- !self.c1_is_active_flag(channel) && self.c1_get_tx_channel(channel)
+ pub fn is_tx_pending(channel: IpccChannel) -> bool {
+ !Self::c1_is_active_flag(channel) && Self::c1_get_tx_channel(channel)
}
- pub fn is_rx_pending(&self, channel: IpccChannel) -> bool {
- 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 _ }
+ pub fn is_rx_pending(channel: IpccChannel) -> bool {
+ Self::c2_is_active_flag(channel) && Self::c1_get_rx_channel(channel)
}
}
diff --git a/embassy-stm32/src/tl_mbox/mm.rs b/embassy-stm32/src/tl_mbox/mm.rs
index f99ffa39..e28a6aa0 100644
--- a/embassy-stm32/src/tl_mbox/mm.rs
+++ b/embassy-stm32/src/tl_mbox/mm.rs
@@ -1,22 +1,20 @@
-use core::mem::MaybeUninit;
-
use super::evt::EvtPacket;
use super::unsafe_linked_list::LinkedListNode;
use super::{
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,
};
-use crate::ipcc::Ipcc;
+use crate::tl_mbox::ipcc::Ipcc;
pub struct MemoryManager;
impl MemoryManager {
- pub fn new() -> Self {
+ pub fn enable() {
unsafe {
LinkedListNode::init_head(FREE_BUFF_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_sys_buffer: SYS_SPARE_EVT_BUF.as_ptr().cast(),
ble_pool: EVT_POOL.as_ptr().cast(),
@@ -26,31 +24,29 @@ impl MemoryManager {
traces_pool_size: 0,
});
}
-
- MemoryManager
}
- pub fn evt_handler(ipcc: &mut Ipcc) {
- ipcc.c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false);
+ pub fn evt_handler() {
+ Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_MM_RELEASE_BUFFER_CHANNEL, false);
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 {
let list_node = evt.cast();
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
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 {
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);
}
}
diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32/src/tl_mbox/mod.rs
index dc6104cc..616f7dc5 100644
--- a/embassy-stm32/src/tl_mbox/mod.rs
+++ b/embassy-stm32/src/tl_mbox/mod.rs
@@ -1,6 +1,9 @@
use core::mem::MaybeUninit;
+use atomic_polyfill::{compiler_fence, Ordering};
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::channel::Channel;
@@ -12,13 +15,16 @@ use self::shci::{shci_ble_init, ShciBleInitCmdParam};
use self::sys::Sys;
use self::unsafe_linked_list::LinkedListNode;
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 channels;
mod cmd;
mod consts;
mod evt;
+mod ipcc;
mod mm;
mod shci;
mod sys;
@@ -58,13 +64,34 @@ pub struct FusInfoTable {
pub struct ReceiveInterruptHandler {}
impl interrupt::Handler 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 {}
impl interrupt::Handler 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
@@ -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
pub(crate) static TL_CHANNEL: Channel = Channel::new();
-pub struct TlMbox {
- _sys: Sys,
- _ble: Ble,
- _mm: MemoryManager,
+pub struct TlMbox<'d> {
+ _ipcc: PeripheralRef<'d, IPCC>,
}
-impl TlMbox {
+impl<'d> TlMbox<'d> {
/// initializes low-level transport between CPU1 and BLE stack on CPU2
- pub fn init(
- ipcc: &mut Ipcc,
+ pub fn new(
+ ipcc: impl Peripheral + 'd,
_irqs: impl interrupt::Binding
+ interrupt::Binding,
- ) -> TlMbox {
+ config: Config,
+ ) -> Self {
+ into_ref!(ipcc);
+
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(),
ble_table: TL_BLE_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(),
});
+ // info!("TL_REF_TABLE addr: {:x}", TL_REF_TABLE.as_ptr() as usize);
+
+ compiler_fence(Ordering::AcqRel);
+
TL_SYS_TABLE = MaybeUninit::zeroed();
TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed();
TL_BLE_TABLE = MaybeUninit::zeroed();
@@ -334,33 +368,24 @@ impl TlMbox {
CS_BUFFER = MaybeUninit::zeroed();
BLE_CMD_BUFFER = MaybeUninit::zeroed();
HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed();
+
+ compiler_fence(Ordering::AcqRel);
}
- ipcc.init();
+ Ipcc::enable(config);
- let _sys = Sys::new(ipcc);
- let _ble = Ble::new(ipcc);
- let _mm = MemoryManager::new();
+ Sys::enable();
+ Ble::enable();
+ MemoryManager::enable();
- // rx_irq.disable();
- // tx_irq.disable();
- //
- // 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();
+ // enable interrupts
+ unsafe { crate::interrupt::IPCC_C1_RX::steal() }.unpend();
+ unsafe { crate::interrupt::IPCC_C1_TX::steal() }.unpend();
- 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 {
@@ -374,42 +399,19 @@ impl TlMbox {
}
}
- pub fn shci_ble_init(&self, ipcc: &mut Ipcc, param: ShciBleInitCmdParam) {
- shci_ble_init(ipcc, param);
+ pub fn shci_ble_init(&self, param: ShciBleInitCmdParam) {
+ shci_ble_init(param);
}
- pub fn send_ble_cmd(&self, ipcc: &mut Ipcc, buf: &[u8]) {
- ble::Ble::send_cmd(ipcc, buf);
+ pub fn send_ble_cmd(&self, buf: &[u8]) {
+ ble::Ble::send_cmd(buf);
}
- // pub fn send_sys_cmd(&self, ipcc: &mut Ipcc, buf: &[u8]) {
- // sys::Sys::send_cmd(ipcc, buf);
+ // pub fn send_sys_cmd(&self, buf: &[u8]) {
+ // sys::Sys::send_cmd(buf);
// }
pub async fn read(&self) -> EvtBox {
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!()
- }
- }
}
diff --git a/embassy-stm32/src/tl_mbox/shci.rs b/embassy-stm32/src/tl_mbox/shci.rs
index 61fd9e4a..6b5b2dd1 100644
--- a/embassy-stm32/src/tl_mbox/shci.rs
+++ b/embassy-stm32/src/tl_mbox/shci.rs
@@ -3,7 +3,7 @@
use super::cmd::CmdPacket;
use super::consts::TlPacketType;
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;
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,
}
-pub fn shci_ble_init(ipcc: &mut Ipcc, param: ShciBleInitCmdParam) {
+pub fn shci_ble_init(param: ShciBleInitCmdParam) {
let mut packet = ShciBleInitCmdPacket {
header: ShciHeader::default(),
param,
@@ -95,7 +95,7 @@ pub fn shci_ble_init(ipcc: &mut Ipcc, param: ShciBleInitCmdParam) {
cmd_buf.cmd_serial.ty = TlPacketType::SysCmd as u8;
- 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_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL);
+ Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true);
}
}
diff --git a/embassy-stm32/src/tl_mbox/sys.rs b/embassy-stm32/src/tl_mbox/sys.rs
index 31ebde72..9685fb92 100644
--- a/embassy-stm32/src/tl_mbox/sys.rs
+++ b/embassy-stm32/src/tl_mbox/sys.rs
@@ -1,5 +1,3 @@
-use core::mem::MaybeUninit;
-
use embassy_futures::block_on;
use super::cmd::{CmdPacket, CmdSerial};
@@ -7,27 +5,25 @@ use super::consts::TlPacketType;
use super::evt::{CcEvt, EvtBox, EvtSerial};
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 crate::ipcc::Ipcc;
+use crate::tl_mbox::ipcc::Ipcc;
pub struct Sys;
impl Sys {
- pub(crate) fn new(ipcc: &mut Ipcc) -> Self {
+ pub fn enable() {
unsafe {
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(),
sys_queue: SYSTEM_EVT_QUEUE.as_ptr(),
});
}
- ipcc.c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true);
-
- Sys
+ Ipcc::c1_set_rx_channel(channels::cpu2::IPCC_SYSTEM_EVENT_CHANNEL, true);
}
- pub(crate) fn evt_handler(ipcc: &mut Ipcc) {
+ pub fn evt_handler() {
unsafe {
let mut node_ptr = core::ptr::null_mut();
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 {
- ipcc.c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, false);
+ pub fn cmd_evt_handler() -> CcEvt {
+ Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, false);
// ST's command response data structure is really convoluted.
//
@@ -68,11 +64,11 @@ impl Sys {
}
#[allow(dead_code)]
- pub(crate) fn send_cmd(ipcc: &mut Ipcc, buf: &[u8]) {
+ pub fn send_cmd(buf: &[u8]) {
unsafe {
// TODO: check this
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();
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;
cmd_packet.cmd_serial.ty = TlPacketType::SysCmd as u8;
- 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_flag_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL);
+ Ipcc::c1_set_tx_channel(channels::cpu1::IPCC_SYSTEM_CMD_RSP_CHANNEL, true);
}
}
}
diff --git a/tests/stm32/memory_ble.x b/embassy-stm32/tl_mbox.x.in
similarity index 58%
rename from tests/stm32/memory_ble.x
rename to embassy-stm32/tl_mbox.x.in
index 4332e2c7..b6eecb42 100644
--- a/tests/stm32/memory_ble.x
+++ b/embassy-stm32/tl_mbox.x.in
@@ -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
}
-/* Place stack at the end of SRAM1 */
-_stack_start = ORIGIN(RAM) + LENGTH(RAM);
-
/*
* Scatter the mailbox interface memory sections in shared memory
*/
-SECTIONS {
+SECTIONS
+{
TL_REF_TABLE (NOLOAD) : { *(TL_REF_TABLE) } >RAM_SHARED
MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml
index 3c7e3e87..8cfac772 100644
--- a/examples/stm32wb/Cargo.toml
+++ b/examples/stm32wb/Cargo.toml
@@ -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", "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-rtt = "0.4"
diff --git a/examples/stm32wb/build.rs b/examples/stm32wb/build.rs
index 30691aa9..29b3a9b2 100644
--- a/examples/stm32wb/build.rs
+++ b/examples/stm32wb/build.rs
@@ -1,35 +1,11 @@
-//! This build script copies the `memory.x` file from the crate root into
-//! 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");
+use std::error::Error;
+fn main() -> Result<(), Box> {
println!("cargo:rustc-link-arg-bins=--nmagic");
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");
+
+ Ok(())
}
diff --git a/examples/stm32wb/memory.x b/examples/stm32wb/memory.x
deleted file mode 100644
index e1f0530b..00000000
--- a/examples/stm32wb/memory.x
+++ /dev/null
@@ -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
-}
diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs
index 326e4be8..8f4e70af 100644
--- a/examples/stm32wb/src/bin/tl_mbox.rs
+++ b/examples/stm32wb/src/bin/tl_mbox.rs
@@ -4,8 +4,7 @@
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::ipcc::{Config, Ipcc};
-use embassy_stm32::tl_mbox::TlMbox;
+use embassy_stm32::tl_mbox::{Config, TlMbox};
use embassy_stm32::{bind_interrupts, tl_mbox};
use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _};
@@ -45,14 +44,12 @@ async fn main(_spawner: Spawner) {
info!("Hello World!");
let config = Config::default();
- let mut ipcc = Ipcc::new(p.IPCC, config);
-
- let mbox = TlMbox::init(&mut ipcc, Irqs);
+ let mbox = TlMbox::new(p.IPCC, Irqs, config);
loop {
let wireless_fw_info = mbox.wireless_fw_info();
match wireless_fw_info {
- None => error!("not yet initialized"),
+ None => info!("not yet initialized"),
Some(fw_info) => {
let version_major = fw_info.version_major();
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();
}
diff --git a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs
index 7a69f26b..1724d946 100644
--- a/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_tx_rx.rs
@@ -4,8 +4,7 @@
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::ipcc::{Config, Ipcc};
-use embassy_stm32::tl_mbox::TlMbox;
+use embassy_stm32::tl_mbox::{Config, TlMbox};
use embassy_stm32::{bind_interrupts, tl_mbox};
use {defmt_rtt as _, panic_probe as _};
@@ -44,12 +43,7 @@ async fn main(_spawner: Spawner) {
info!("Hello World!");
let config = Config::default();
- let mut ipcc = Ipcc::new(p.IPCC, config);
-
- let mbox = TlMbox::init(&mut ipcc, Irqs);
-
- // initialize ble stack, does not return a response
- mbox.shci_ble_init(&mut ipcc, Default::default());
+ let mbox = TlMbox::new(p.IPCC, Irqs, config);
info!("waiting for coprocessor to boot");
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");
- 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;
@@ -92,8 +87,12 @@ async fn main(_spawner: Spawner) {
info!(
"==> 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();
}
diff --git a/tests/stm32/.cargo/config.toml b/tests/stm32/.cargo/config.toml
index 29c4799a..426d6e67 100644
--- a/tests/stm32/.cargo/config.toml
+++ b/tests/stm32/.cargo/config.toml
@@ -17,4 +17,4 @@ rustflags = [
target = "thumbv7m-none-eabi"
[env]
-DEFMT_LOG = "trace"
+DEFMT_LOG = "trace"
\ No newline at end of file
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index bd8d90ab..4c059774 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -7,12 +7,12 @@ autobins = false
[features]
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
stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo
stm32g491re = ["embassy-stm32/stm32g491re", "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
stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board
@@ -45,8 +45,8 @@ 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"
+name = "tl_mbox"
+path = "src/bin/tl_mbox.rs"
required-features = [ "ble",]
[[bin]]
diff --git a/tests/stm32/build.rs b/tests/stm32/build.rs
index ca76b70b..b4583147 100644
--- a/tests/stm32/build.rs
+++ b/tests/stm32/build.rs
@@ -9,17 +9,22 @@ fn main() -> Result<(), Box> {
println!("cargo:rustc-link-arg-bins=--nmagic");
// 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: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 {
println!("cargo:rustc-link-arg-bins=-Tlink_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");
Ok(())
diff --git a/tests/stm32/src/bin/ble.rs b/tests/stm32/src/bin/tl_mbox.rs
similarity index 79%
rename from tests/stm32/src/bin/ble.rs
rename to tests/stm32/src/bin/tl_mbox.rs
index aedf9a38..626e7ac6 100644
--- a/tests/stm32/src/bin/ble.rs
+++ b/tests/stm32/src/bin/tl_mbox.rs
@@ -7,24 +7,23 @@
#[path = "../example_common.rs"]
mod example_common;
use embassy_executor::Spawner;
-use embassy_stm32::interrupt;
-use embassy_stm32::ipcc::{Config, Ipcc};
-use embassy_stm32::tl_mbox::TlMbox;
+use embassy_stm32::tl_mbox::{Config, TlMbox};
+use embassy_stm32::{bind_interrupts, tl_mbox};
use embassy_time::{Duration, Timer};
use example_common::*;
+bind_interrupts!(struct Irqs{
+ IPCC_C1_RX => tl_mbox::ReceiveInterruptHandler;
+ IPCC_C1_TX => tl_mbox::TransmitInterruptHandler;
+});
+
#[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 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);
+ let mbox = TlMbox::new(p.IPCC, Irqs, config);
loop {
let wireless_fw_info = mbox.wireless_fw_info();