2023-06-12 13:27:51 +02:00
|
|
|
#![no_std]
|
|
|
|
|
|
|
|
// This must go FIRST so that all the other modules see its macros.
|
|
|
|
pub mod fmt;
|
|
|
|
|
2023-05-02 13:16:48 +02:00
|
|
|
use core::mem::MaybeUninit;
|
2023-06-14 00:12:34 +02:00
|
|
|
use core::sync::atomic::{compiler_fence, Ordering};
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-06-12 13:27:51 +02:00
|
|
|
use cmd::CmdPacket;
|
2023-05-27 22:05:23 +02:00
|
|
|
use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
|
2023-06-12 13:27:51 +02:00
|
|
|
use embassy_stm32::interrupt;
|
2023-06-12 15:44:30 +02:00
|
|
|
use embassy_stm32::interrupt::typelevel::Interrupt;
|
2023-06-17 19:00:33 +02:00
|
|
|
use embassy_stm32::ipcc::{Config, Ipcc, ReceiveInterruptHandler, TransmitInterruptHandler};
|
2023-06-12 13:27:51 +02:00
|
|
|
use embassy_stm32::peripherals::IPCC;
|
2023-05-15 11:25:02 +02:00
|
|
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
|
|
|
use embassy_sync::channel::Channel;
|
2023-06-08 17:26:47 +02:00
|
|
|
use embassy_sync::signal::Signal;
|
2023-06-12 13:27:51 +02:00
|
|
|
use evt::{CcEvt, EvtBox};
|
|
|
|
use tables::{
|
|
|
|
BleTable, DeviceInfoTable, Mac802_15_4Table, MemManagerTable, RefTable, SysTable, ThreadTable, TracesTable,
|
|
|
|
WirelessFwInfoTable,
|
|
|
|
};
|
|
|
|
use unsafe_linked_list::LinkedListNode;
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-06-08 17:26:47 +02:00
|
|
|
pub mod ble;
|
|
|
|
pub mod channels;
|
|
|
|
pub mod cmd;
|
|
|
|
pub mod consts;
|
|
|
|
pub mod evt;
|
|
|
|
pub mod mm;
|
|
|
|
pub mod shci;
|
|
|
|
pub mod sys;
|
2023-06-12 13:27:51 +02:00
|
|
|
pub mod tables;
|
2023-06-08 17:26:47 +02:00
|
|
|
pub mod unsafe_linked_list;
|
2023-05-02 13:16:48 +02:00
|
|
|
|
|
|
|
#[link_section = "TL_REF_TABLE"]
|
|
|
|
pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit();
|
|
|
|
|
2023-05-04 12:02:17 +02:00
|
|
|
#[link_section = "MB_MEM1"]
|
2023-05-02 13:16:48 +02:00
|
|
|
static mut TL_DEVICE_INFO_TABLE: MaybeUninit<DeviceInfoTable> = MaybeUninit::uninit();
|
|
|
|
|
2023-05-04 12:02:17 +02:00
|
|
|
#[link_section = "MB_MEM1"]
|
2023-05-02 13:16:48 +02:00
|
|
|
static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit();
|
|
|
|
|
2023-05-04 12:02:17 +02:00
|
|
|
#[link_section = "MB_MEM1"]
|
2023-05-02 13:16:48 +02:00
|
|
|
static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit();
|
|
|
|
|
2023-05-04 12:02:17 +02:00
|
|
|
#[link_section = "MB_MEM1"]
|
2023-05-02 13:16:48 +02:00
|
|
|
static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit();
|
|
|
|
|
2023-05-04 12:02:17 +02:00
|
|
|
#[link_section = "MB_MEM1"]
|
2023-05-02 13:16:48 +02:00
|
|
|
static mut TL_MEM_MANAGER_TABLE: MaybeUninit<MemManagerTable> = MaybeUninit::uninit();
|
|
|
|
|
2023-05-04 12:02:17 +02:00
|
|
|
#[link_section = "MB_MEM1"]
|
2023-05-02 13:16:48 +02:00
|
|
|
static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit();
|
|
|
|
|
2023-05-04 12:02:17 +02:00
|
|
|
#[link_section = "MB_MEM1"]
|
2023-05-02 13:16:48 +02:00
|
|
|
static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit();
|
|
|
|
|
2023-06-08 17:26:47 +02:00
|
|
|
#[link_section = "MB_MEM2"]
|
|
|
|
static mut FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
|
|
|
|
|
|
|
|
// Not in shared RAM
|
|
|
|
static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
|
2023-05-12 11:26:46 +02:00
|
|
|
|
2023-05-26 12:26:58 +02:00
|
|
|
#[allow(dead_code)] // Not used currently but reserved
|
2023-06-08 17:26:47 +02:00
|
|
|
#[link_section = "MB_MEM2"]
|
|
|
|
static mut TRACES_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-06-08 17:26:47 +02:00
|
|
|
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::<evt::CsEvt>();
|
2023-05-26 12:26:58 +02:00
|
|
|
|
2023-05-04 12:02:17 +02:00
|
|
|
#[link_section = "MB_MEM2"]
|
2023-05-02 13:16:48 +02:00
|
|
|
static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> =
|
|
|
|
MaybeUninit::uninit();
|
|
|
|
|
2023-05-26 12:26:58 +02:00
|
|
|
#[link_section = "MB_MEM2"]
|
2023-05-02 13:16:48 +02:00
|
|
|
static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
|
|
|
|
|
2023-05-15 11:25:02 +02:00
|
|
|
#[link_section = "MB_MEM2"]
|
2023-05-02 13:16:48 +02:00
|
|
|
static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit();
|
|
|
|
|
2023-05-25 17:39:43 +02:00
|
|
|
#[link_section = "MB_MEM2"]
|
2023-06-08 17:26:47 +02:00
|
|
|
pub static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Queue length of BLE Event
|
|
|
|
* This parameter defines the number of asynchronous events that can be stored in the HCI layer before
|
|
|
|
* being reported to the application. When a command is sent to the BLE core coprocessor, the HCI layer
|
|
|
|
* is waiting for the event with the Num_HCI_Command_Packets set to 1. The receive queue shall be large
|
|
|
|
* enough to store all asynchronous events received in between.
|
|
|
|
* When CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE is set to 27, this allow to store three 255 bytes long asynchronous events
|
|
|
|
* between the HCI command and its event.
|
|
|
|
* This parameter depends on the value given to CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE. When the queue size is to small,
|
|
|
|
* the system may hang if the queue is full with asynchronous events and the HCI layer is still waiting
|
|
|
|
* for a CC/CS event, In that case, the notification TL_BLE_HCI_ToNot() is called to indicate
|
|
|
|
* to the application a HCI command did not receive its command event within 30s (Default HCI Timeout).
|
|
|
|
*/
|
|
|
|
const CFG_TLBLE_EVT_QUEUE_LENGTH: usize = 5;
|
|
|
|
const CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255;
|
|
|
|
const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TLBLE_MOST_EVENT_PAYLOAD_SIZE;
|
|
|
|
|
|
|
|
const fn divc(x: usize, y: usize) -> usize {
|
|
|
|
((x) + (y) - 1) / (y)
|
|
|
|
}
|
|
|
|
|
|
|
|
const POOL_SIZE: usize = CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4);
|
2023-05-25 17:39:43 +02:00
|
|
|
|
2023-05-04 12:02:17 +02:00
|
|
|
#[link_section = "MB_MEM2"]
|
2023-05-26 12:26:58 +02:00
|
|
|
static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit();
|
2023-05-25 17:39:43 +02:00
|
|
|
|
|
|
|
#[link_section = "MB_MEM2"]
|
2023-05-26 12:26:58 +02:00
|
|
|
static mut SYS_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
|
2023-05-02 13:16:48 +02:00
|
|
|
MaybeUninit::uninit();
|
|
|
|
|
2023-05-04 12:02:17 +02:00
|
|
|
#[link_section = "MB_MEM2"]
|
2023-05-25 17:39:43 +02:00
|
|
|
static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> =
|
|
|
|
MaybeUninit::uninit();
|
|
|
|
|
2023-05-26 12:26:58 +02:00
|
|
|
#[link_section = "MB_MEM2"]
|
2023-05-02 13:16:48 +02:00
|
|
|
static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit();
|
|
|
|
|
2023-05-04 12:02:17 +02:00
|
|
|
#[link_section = "MB_MEM2"]
|
2023-06-08 17:26:47 +02:00
|
|
|
// fuck these "magic" numbers from ST ---v---v
|
2023-05-02 13:16:48 +02:00
|
|
|
static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit();
|
|
|
|
|
2023-06-17 19:06:00 +02:00
|
|
|
// TODO: remove these items
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
2023-06-08 17:26:47 +02:00
|
|
|
/// current event that is produced during IPCC IRQ handler execution
|
|
|
|
/// on SYS channel
|
2023-06-12 13:27:51 +02:00
|
|
|
static EVT_CHANNEL: Channel<CriticalSectionRawMutex, EvtBox, 32> = Channel::new();
|
|
|
|
|
2023-06-17 19:06:00 +02:00
|
|
|
#[allow(dead_code)]
|
2023-06-08 17:26:47 +02:00
|
|
|
/// last received Command Complete event
|
|
|
|
static LAST_CC_EVT: Signal<CriticalSectionRawMutex, CcEvt> = Signal::new();
|
2023-05-15 11:25:02 +02:00
|
|
|
|
2023-06-12 13:27:51 +02:00
|
|
|
static STATE: Signal<CriticalSectionRawMutex, ()> = Signal::new();
|
2023-06-08 17:26:47 +02:00
|
|
|
|
2023-06-12 13:27:51 +02:00
|
|
|
pub struct TlMbox<'d> {
|
2023-05-27 22:05:23 +02:00
|
|
|
_ipcc: PeripheralRef<'d, IPCC>,
|
2023-05-02 13:16:48 +02:00
|
|
|
}
|
|
|
|
|
2023-05-27 22:05:23 +02:00
|
|
|
impl<'d> TlMbox<'d> {
|
2023-06-12 13:27:51 +02:00
|
|
|
pub fn init(
|
2023-05-27 22:05:23 +02:00
|
|
|
ipcc: impl Peripheral<P = IPCC> + 'd,
|
2023-06-12 15:44:30 +02:00
|
|
|
_irqs: impl interrupt::typelevel::Binding<interrupt::typelevel::IPCC_C1_RX, ReceiveInterruptHandler>
|
|
|
|
+ interrupt::typelevel::Binding<interrupt::typelevel::IPCC_C1_TX, TransmitInterruptHandler>,
|
2023-05-26 10:56:55 +02:00
|
|
|
config: Config,
|
2023-05-27 22:05:23 +02:00
|
|
|
) -> Self {
|
|
|
|
into_ref!(ipcc);
|
|
|
|
|
2023-05-02 13:16:48 +02:00
|
|
|
unsafe {
|
2023-06-14 00:12:34 +02:00
|
|
|
TL_REF_TABLE.as_mut_ptr().write_volatile(RefTable {
|
|
|
|
device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(),
|
2023-05-02 13:16:48 +02:00
|
|
|
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(),
|
2023-06-14 00:12:34 +02:00
|
|
|
// zigbee_table: TL_ZIGBEE_TABLE.as_ptr(),
|
|
|
|
// lld_tests_table: TL_LLD_TESTS_TABLE.as_ptr(),
|
|
|
|
// ble_lld_table: TL_BLE_LLD_TABLE.as_ptr(),
|
2023-05-02 13:16:48 +02:00
|
|
|
});
|
|
|
|
|
2023-06-14 00:12:34 +02:00
|
|
|
TL_SYS_TABLE
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
TL_DEVICE_INFO_TABLE
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
TL_BLE_TABLE
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
TL_THREAD_TABLE
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
TL_MEM_MANAGER_TABLE
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
|
|
|
|
TL_TRACES_TABLE
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
TL_MAC_802_15_4_TABLE
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
2023-06-14 00:17:10 +02:00
|
|
|
// TL_ZIGBEE_TABLE
|
|
|
|
// .as_mut_ptr()
|
|
|
|
// .write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
// TL_LLD_TESTS_TABLE
|
|
|
|
// .as_mut_ptr()
|
|
|
|
// .write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
// TL_BLE_LLD_TABLE
|
|
|
|
// .as_mut_ptr()
|
|
|
|
// .write_volatile(MaybeUninit::zeroed().assume_init());
|
2023-06-14 00:12:34 +02:00
|
|
|
|
|
|
|
EVT_POOL
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
SYS_SPARE_EVT_BUF
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
BLE_SPARE_EVT_BUF
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
|
|
|
|
{
|
|
|
|
BLE_CMD_BUFFER
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
HCI_ACL_DATA_BUFFER
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
CS_BUFFER
|
|
|
|
.as_mut_ptr()
|
|
|
|
.write_volatile(MaybeUninit::zeroed().assume_init());
|
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
}
|
|
|
|
|
2023-06-14 00:12:34 +02:00
|
|
|
compiler_fence(Ordering::SeqCst);
|
|
|
|
|
2023-05-27 22:05:23 +02:00
|
|
|
Ipcc::enable(config);
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-06-12 13:27:51 +02:00
|
|
|
sys::Sys::enable();
|
|
|
|
ble::Ble::enable();
|
|
|
|
mm::MemoryManager::enable();
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-05-26 10:56:55 +02:00
|
|
|
// enable interrupts
|
2023-06-12 15:44:30 +02:00
|
|
|
interrupt::typelevel::IPCC_C1_RX::unpend();
|
|
|
|
interrupt::typelevel::IPCC_C1_TX::unpend();
|
2023-05-26 10:56:55 +02:00
|
|
|
|
2023-06-12 15:44:30 +02:00
|
|
|
unsafe { interrupt::typelevel::IPCC_C1_RX::enable() };
|
|
|
|
unsafe { interrupt::typelevel::IPCC_C1_TX::enable() };
|
2023-05-15 11:25:02 +02:00
|
|
|
|
2023-06-12 13:27:51 +02:00
|
|
|
STATE.reset();
|
|
|
|
|
|
|
|
Self { _ipcc: ipcc }
|
2023-05-02 13:16:48 +02:00
|
|
|
}
|
|
|
|
|
2023-06-08 17:26:47 +02:00
|
|
|
/// Returns CPU2 wireless firmware information (if present).
|
2023-05-02 13:16:48 +02:00
|
|
|
pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> {
|
|
|
|
let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table };
|
|
|
|
|
2023-06-08 17:26:47 +02:00
|
|
|
// Zero version indicates that CPU2 wasn't active and didn't fill the information table
|
2023-05-02 13:16:48 +02:00
|
|
|
if info.version != 0 {
|
|
|
|
Some(*info)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|