diff options
Diffstat (limited to 'embassy-stm32/src/tl_mbox/mod.rs')
| -rw-r--r-- | embassy-stm32/src/tl_mbox/mod.rs | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/embassy-stm32/src/tl_mbox/mod.rs b/embassy-stm32/src/tl_mbox/mod.rs new file mode 100644 index 000000000..623546dc9 --- /dev/null +++ b/embassy-stm32/src/tl_mbox/mod.rs | |||
| @@ -0,0 +1,318 @@ | |||
| 1 | use core::mem::MaybeUninit; | ||
| 2 | |||
| 3 | use bit_field::BitField; | ||
| 4 | |||
| 5 | use self::ble::Ble; | ||
| 6 | use self::cmd::{AclDataPacket, CmdPacket}; | ||
| 7 | use self::evt::CsEvt; | ||
| 8 | use self::mm::MemoryManager; | ||
| 9 | use self::sys::Sys; | ||
| 10 | use self::unsafe_linked_list::LinkedListNode; | ||
| 11 | use crate::ipcc::Ipcc; | ||
| 12 | |||
| 13 | mod ble; | ||
| 14 | mod channels; | ||
| 15 | mod cmd; | ||
| 16 | mod evt; | ||
| 17 | mod mm; | ||
| 18 | mod sys; | ||
| 19 | mod unsafe_linked_list; | ||
| 20 | |||
| 21 | pub type PacketHeader = LinkedListNode; | ||
| 22 | |||
| 23 | const TL_PACKET_HEADER_SIZE: usize = core::mem::size_of::<PacketHeader>(); | ||
| 24 | const TL_EVT_HEADER_SIZE: usize = 3; | ||
| 25 | const TL_CS_EVT_SIZE: usize = core::mem::size_of::<CsEvt>(); | ||
| 26 | |||
| 27 | const CFG_TL_BLE_EVT_QUEUE_LENGTH: usize = 5; | ||
| 28 | const CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE: usize = 255; | ||
| 29 | const TL_BLE_EVENT_FRAME_SIZE: usize = TL_EVT_HEADER_SIZE + CFG_TL_BLE_MOST_EVENT_PAYLOAD_SIZE; | ||
| 30 | |||
| 31 | const POOL_SIZE: usize = CFG_TL_BLE_EVT_QUEUE_LENGTH * 4 * divc(TL_PACKET_HEADER_SIZE + TL_BLE_EVENT_FRAME_SIZE, 4); | ||
| 32 | |||
| 33 | const fn divc(x: usize, y: usize) -> usize { | ||
| 34 | (x + y - 1) / y | ||
| 35 | } | ||
| 36 | |||
| 37 | #[repr(C, packed)] | ||
| 38 | #[derive(Copy, Clone)] | ||
| 39 | pub struct SafeBootInfoTable { | ||
| 40 | version: u32, | ||
| 41 | } | ||
| 42 | |||
| 43 | #[repr(C, packed)] | ||
| 44 | #[derive(Copy, Clone)] | ||
| 45 | pub struct RssInfoTable { | ||
| 46 | version: u32, | ||
| 47 | memory_size: u32, | ||
| 48 | rss_info: u32, | ||
| 49 | } | ||
| 50 | |||
| 51 | /// # Version | ||
| 52 | /// - 0 -> 3 = Build - 0: Untracked - 15:Released - x: Tracked version | ||
| 53 | /// - 4 -> 7 = branch - 0: Mass Market - x: ... | ||
| 54 | /// - 8 -> 15 = Subversion | ||
| 55 | /// - 16 -> 23 = Version minor | ||
| 56 | /// - 24 -> 31 = Version major | ||
| 57 | /// # Memory Size | ||
| 58 | /// - 0 -> 7 = Flash ( Number of 4k sector) | ||
| 59 | /// - 8 -> 15 = Reserved ( Shall be set to 0 - may be used as flash extension ) | ||
| 60 | /// - 16 -> 23 = SRAM2b ( Number of 1k sector) | ||
| 61 | /// - 24 -> 31 = SRAM2a ( Number of 1k sector) | ||
| 62 | #[repr(C, packed)] | ||
| 63 | #[derive(Copy, Clone)] | ||
| 64 | pub struct WirelessFwInfoTable { | ||
| 65 | version: u32, | ||
| 66 | memory_size: u32, | ||
| 67 | thread_info: u32, | ||
| 68 | ble_info: u32, | ||
| 69 | } | ||
| 70 | |||
| 71 | impl WirelessFwInfoTable { | ||
| 72 | pub fn version_major(&self) -> u8 { | ||
| 73 | let version = self.version; | ||
| 74 | (version.get_bits(24..31) & 0xff) as u8 | ||
| 75 | } | ||
| 76 | |||
| 77 | pub fn version_minor(&self) -> u8 { | ||
| 78 | let version = self.version; | ||
| 79 | (version.get_bits(16..23) & 0xff) as u8 | ||
| 80 | } | ||
| 81 | |||
| 82 | pub fn subversion(&self) -> u8 { | ||
| 83 | let version = self.version; | ||
| 84 | (version.get_bits(8..15) & 0xff) as u8 | ||
| 85 | } | ||
| 86 | |||
| 87 | /// size of FLASH, expressed in number of 4K sectors | ||
| 88 | pub fn flash_size(&self) -> u8 { | ||
| 89 | let memory_size = self.memory_size; | ||
| 90 | (memory_size.get_bits(0..7) & 0xff) as u8 | ||
| 91 | } | ||
| 92 | |||
| 93 | /// size for SRAM2a, expressed in number of 1K sectors | ||
| 94 | pub fn sram2a_size(&self) -> u8 { | ||
| 95 | let memory_size = self.memory_size; | ||
| 96 | (memory_size.get_bits(24..31) & 0xff) as u8 | ||
| 97 | } | ||
| 98 | |||
| 99 | /// size of SRAM2b, expressed in number of 1K sectors | ||
| 100 | pub fn sram2b_size(&self) -> u8 { | ||
| 101 | let memory_size = self.memory_size; | ||
| 102 | (memory_size.get_bits(16..23) & 0xff) as u8 | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | #[repr(C, packed)] | ||
| 107 | #[derive(Copy, Clone)] | ||
| 108 | pub struct DeviceInfoTable { | ||
| 109 | pub safe_boot_info_table: SafeBootInfoTable, | ||
| 110 | pub rss_info_table: RssInfoTable, | ||
| 111 | pub wireless_fw_info_table: WirelessFwInfoTable, | ||
| 112 | } | ||
| 113 | |||
| 114 | #[repr(C, packed)] | ||
| 115 | struct BleTable { | ||
| 116 | pcmd_buffer: *const CmdPacket, | ||
| 117 | pcs_buffer: *const u8, | ||
| 118 | pevt_queue: *const u8, | ||
| 119 | phci_acl_data_buffer: *mut AclDataPacket, | ||
| 120 | } | ||
| 121 | |||
| 122 | #[repr(C, packed)] | ||
| 123 | struct ThreadTable { | ||
| 124 | no_stack_buffer: *const u8, | ||
| 125 | cli_cmd_rsp_buffer: *const u8, | ||
| 126 | ot_cmd_rsp_buffer: *const u8, | ||
| 127 | } | ||
| 128 | |||
| 129 | #[repr(C, packed)] | ||
| 130 | struct SysTable { | ||
| 131 | pcmd_buffer: *mut CmdPacket, | ||
| 132 | sys_queue: *const LinkedListNode, | ||
| 133 | } | ||
| 134 | |||
| 135 | #[allow(dead_code)] // Not used currently but reserved | ||
| 136 | #[repr(C, packed)] | ||
| 137 | struct LldTestTable { | ||
| 138 | cli_cmd_rsp_buffer: *const u8, | ||
| 139 | m0_cmd_buffer: *const u8, | ||
| 140 | } | ||
| 141 | |||
| 142 | #[allow(dead_code)] // Not used currently but reserved | ||
| 143 | #[repr(C, packed)] | ||
| 144 | struct BleLldTable { | ||
| 145 | cmd_rsp_buffer: *const u8, | ||
| 146 | m0_cmd_buffer: *const u8, | ||
| 147 | } | ||
| 148 | |||
| 149 | #[allow(dead_code)] // Not used currently but reserved | ||
| 150 | #[repr(C, packed)] | ||
| 151 | struct ZigbeeTable { | ||
| 152 | notif_m0_to_m4_buffer: *const u8, | ||
| 153 | appli_cmd_m4_to_m0_buffer: *const u8, | ||
| 154 | request_m0_to_m4_buffer: *const u8, | ||
| 155 | } | ||
| 156 | |||
| 157 | #[repr(C, packed)] | ||
| 158 | struct MemManagerTable { | ||
| 159 | spare_ble_buffer: *const u8, | ||
| 160 | spare_sys_buffer: *const u8, | ||
| 161 | |||
| 162 | ble_pool: *const u8, | ||
| 163 | ble_pool_size: u32, | ||
| 164 | |||
| 165 | pevt_free_buffer_queue: *mut LinkedListNode, | ||
| 166 | |||
| 167 | traces_evt_pool: *const u8, | ||
| 168 | traces_pool_size: u32, | ||
| 169 | } | ||
| 170 | |||
| 171 | #[repr(C, packed)] | ||
| 172 | struct TracesTable { | ||
| 173 | traces_queue: *const u8, | ||
| 174 | } | ||
| 175 | |||
| 176 | #[repr(C, packed)] | ||
| 177 | struct Mac802_15_4Table { | ||
| 178 | pcmd_rsp_buffer: *const u8, | ||
| 179 | pnotack_buffer: *const u8, | ||
| 180 | evt_queue: *const u8, | ||
| 181 | } | ||
| 182 | |||
| 183 | /// reference table. Contains pointers to all other tables | ||
| 184 | #[repr(C, packed)] | ||
| 185 | #[derive(Copy, Clone)] | ||
| 186 | pub struct RefTable { | ||
| 187 | pub device_info_table: *const DeviceInfoTable, | ||
| 188 | ble_table: *const BleTable, | ||
| 189 | thread_table: *const ThreadTable, | ||
| 190 | sys_table: *const SysTable, | ||
| 191 | mem_manager_table: *const MemManagerTable, | ||
| 192 | traces_table: *const TracesTable, | ||
| 193 | mac_802_15_4_table: *const Mac802_15_4Table, | ||
| 194 | } | ||
| 195 | |||
| 196 | #[link_section = "TL_REF_TABLE"] | ||
| 197 | pub static mut TL_REF_TABLE: MaybeUninit<RefTable> = MaybeUninit::uninit(); | ||
| 198 | |||
| 199 | #[link_section = "TL_DEVICE_INFO_TABLE"] | ||
| 200 | static mut TL_DEVICE_INFO_TABLE: MaybeUninit<DeviceInfoTable> = MaybeUninit::uninit(); | ||
| 201 | |||
| 202 | #[link_section = "TL_BLE_TABLE"] | ||
| 203 | static mut TL_BLE_TABLE: MaybeUninit<BleTable> = MaybeUninit::uninit(); | ||
| 204 | |||
| 205 | #[link_section = "TL_THREAD_TABLE"] | ||
| 206 | static mut TL_THREAD_TABLE: MaybeUninit<ThreadTable> = MaybeUninit::uninit(); | ||
| 207 | |||
| 208 | #[link_section = "TL_SYS_TABLE"] | ||
| 209 | static mut TL_SYS_TABLE: MaybeUninit<SysTable> = MaybeUninit::uninit(); | ||
| 210 | |||
| 211 | #[link_section = "TL_MEM_MANAGER_TABLE"] | ||
| 212 | static mut TL_MEM_MANAGER_TABLE: MaybeUninit<MemManagerTable> = MaybeUninit::uninit(); | ||
| 213 | |||
| 214 | #[link_section = "TL_TRACES_TABLE"] | ||
| 215 | static mut TL_TRACES_TABLE: MaybeUninit<TracesTable> = MaybeUninit::uninit(); | ||
| 216 | |||
| 217 | #[link_section = "TL_MAC_802_15_4_TABLE"] | ||
| 218 | static mut TL_MAC_802_15_4_TABLE: MaybeUninit<Mac802_15_4Table> = MaybeUninit::uninit(); | ||
| 219 | |||
| 220 | #[allow(dead_code)] // Not used currently but reserved | ||
| 221 | #[link_section = "FREE_BUF_QUEUE"] | ||
| 222 | static mut FREE_BUFF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 223 | |||
| 224 | // not in shared RAM | ||
| 225 | static mut LOCAL_FREE_BUF_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 226 | |||
| 227 | #[allow(dead_code)] // Not used currently but reserved | ||
| 228 | #[link_section = "TRACES_EVT_QUEUE"] | ||
| 229 | static mut TRACES_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 230 | |||
| 231 | #[link_section = "CS_BUFFER"] | ||
| 232 | static mut CS_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + TL_CS_EVT_SIZE]> = | ||
| 233 | MaybeUninit::uninit(); | ||
| 234 | |||
| 235 | #[link_section = "EVT_QUEUE"] | ||
| 236 | static mut EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 237 | |||
| 238 | #[link_section = "SYSTEM_EVT_QUEUE"] | ||
| 239 | static mut SYSTEM_EVT_QUEUE: MaybeUninit<LinkedListNode> = MaybeUninit::uninit(); | ||
| 240 | |||
| 241 | #[link_section = "SYS_CMD_BUF"] | ||
| 242 | static mut SYS_CMD_BUF: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); | ||
| 243 | |||
| 244 | #[link_section = "EVT_POOL"] | ||
| 245 | static mut EVT_POOL: MaybeUninit<[u8; POOL_SIZE]> = MaybeUninit::uninit(); | ||
| 246 | |||
| 247 | #[link_section = "SYS_SPARE_EVT_BUF"] | ||
| 248 | static mut SYS_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> = | ||
| 249 | MaybeUninit::uninit(); | ||
| 250 | |||
| 251 | #[link_section = "BLE_SPARE_EVT_BUF"] | ||
| 252 | static mut BLE_SPARE_EVT_BUF: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + TL_EVT_HEADER_SIZE + 255]> = | ||
| 253 | MaybeUninit::uninit(); | ||
| 254 | |||
| 255 | #[link_section = "BLE_CMD_BUFFER"] | ||
| 256 | static mut BLE_CMD_BUFFER: MaybeUninit<CmdPacket> = MaybeUninit::uninit(); | ||
| 257 | |||
| 258 | #[link_section = "HCI_ACL_DATA_BUFFER"] | ||
| 259 | // "magic" numbers from ST ---v---v | ||
| 260 | static mut HCI_ACL_DATA_BUFFER: MaybeUninit<[u8; TL_PACKET_HEADER_SIZE + 5 + 251]> = MaybeUninit::uninit(); | ||
| 261 | |||
| 262 | pub struct TlMbox { | ||
| 263 | _sys: Sys, | ||
| 264 | _ble: Ble, | ||
| 265 | _mm: MemoryManager, | ||
| 266 | } | ||
| 267 | |||
| 268 | impl TlMbox { | ||
| 269 | /// initializes low-level transport between CPU1 and BLE stack on CPU2 | ||
| 270 | pub fn init(ipcc: &mut Ipcc) -> TlMbox { | ||
| 271 | unsafe { | ||
| 272 | TL_REF_TABLE = MaybeUninit::new(RefTable { | ||
| 273 | device_info_table: TL_DEVICE_INFO_TABLE.as_ptr(), | ||
| 274 | ble_table: TL_BLE_TABLE.as_ptr(), | ||
| 275 | thread_table: TL_THREAD_TABLE.as_ptr(), | ||
| 276 | sys_table: TL_SYS_TABLE.as_ptr(), | ||
| 277 | mem_manager_table: TL_MEM_MANAGER_TABLE.as_ptr(), | ||
| 278 | traces_table: TL_TRACES_TABLE.as_ptr(), | ||
| 279 | mac_802_15_4_table: TL_MAC_802_15_4_TABLE.as_ptr(), | ||
| 280 | }); | ||
| 281 | |||
| 282 | TL_SYS_TABLE = MaybeUninit::zeroed(); | ||
| 283 | TL_DEVICE_INFO_TABLE = MaybeUninit::zeroed(); | ||
| 284 | TL_BLE_TABLE = MaybeUninit::zeroed(); | ||
| 285 | TL_THREAD_TABLE = MaybeUninit::zeroed(); | ||
| 286 | TL_MEM_MANAGER_TABLE = MaybeUninit::zeroed(); | ||
| 287 | TL_TRACES_TABLE = MaybeUninit::zeroed(); | ||
| 288 | TL_MAC_802_15_4_TABLE = MaybeUninit::zeroed(); | ||
| 289 | |||
| 290 | EVT_POOL = MaybeUninit::zeroed(); | ||
| 291 | SYS_SPARE_EVT_BUF = MaybeUninit::zeroed(); | ||
| 292 | BLE_SPARE_EVT_BUF = MaybeUninit::zeroed(); | ||
| 293 | |||
| 294 | CS_BUFFER = MaybeUninit::zeroed(); | ||
| 295 | BLE_CMD_BUFFER = MaybeUninit::zeroed(); | ||
| 296 | HCI_ACL_DATA_BUFFER = MaybeUninit::zeroed(); | ||
| 297 | } | ||
| 298 | |||
| 299 | ipcc.init(); | ||
| 300 | |||
| 301 | let _sys = Sys::new(ipcc); | ||
| 302 | let _ble = Ble::new(ipcc); | ||
| 303 | let _mm = MemoryManager::new(); | ||
| 304 | |||
| 305 | TlMbox { _sys, _ble, _mm } | ||
| 306 | } | ||
| 307 | |||
| 308 | pub fn wireless_fw_info(&self) -> Option<WirelessFwInfoTable> { | ||
| 309 | let info = unsafe { &(*(*TL_REF_TABLE.as_ptr()).device_info_table).wireless_fw_info_table }; | ||
| 310 | |||
| 311 | // zero version indicates that CPU2 wasn't active and didn't fill the information table | ||
| 312 | if info.version != 0 { | ||
| 313 | Some(*info) | ||
| 314 | } else { | ||
| 315 | None | ||
| 316 | } | ||
| 317 | } | ||
| 318 | } | ||
