diff options
| -rw-r--r-- | embassy-stm32-wpan/src/wba/linklayer_plat.rs | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/embassy-stm32-wpan/src/wba/linklayer_plat.rs b/embassy-stm32-wpan/src/wba/linklayer_plat.rs index f53783666..be9c49ab3 100644 --- a/embassy-stm32-wpan/src/wba/linklayer_plat.rs +++ b/embassy-stm32-wpan/src/wba/linklayer_plat.rs | |||
| @@ -1,6 +1,84 @@ | |||
| 1 | // /* USER CODE BEGIN Header */ | ||
| 2 | // /** | ||
| 3 | // ****************************************************************************** | ||
| 4 | // * @file linklayer_plat.c | ||
| 5 | // * @author MCD Application Team | ||
| 6 | // * @brief Source file for the linklayer plateform adaptation layer | ||
| 7 | // ****************************************************************************** | ||
| 8 | // * @attention | ||
| 9 | // * | ||
| 10 | // * Copyright (c) 2024 STMicroelectronics. | ||
| 11 | // * All rights reserved. | ||
| 12 | // * | ||
| 13 | // * This software is licensed under terms that can be found in the LICENSE file | ||
| 14 | // * in the root directory of this software component. | ||
| 15 | // * If no LICENSE file comes with this software, it is provided AS-IS. | ||
| 16 | // * | ||
| 17 | // ****************************************************************************** | ||
| 18 | // */ | ||
| 19 | // /* USER CODE END Header */ | ||
| 20 | // | ||
| 21 | // #include "stm32wbaxx_hal.h" | ||
| 22 | // #include "stm32wbaxx_hal_conf.h" | ||
| 23 | // #include "stm32wbaxx_ll_rcc.h" | ||
| 24 | // | ||
| 25 | // #include "app_common.h" | ||
| 26 | // #include "app_conf.h" | ||
| 27 | // #include "linklayer_plat.h" | ||
| 28 | // #include "scm.h" | ||
| 29 | // #include "log_module.h" | ||
| 30 | // #if (USE_TEMPERATURE_BASED_RADIO_CALIBRATION == 1) | ||
| 31 | // #include "adc_ctrl.h" | ||
| 32 | // #endif /* (USE_TEMPERATURE_BASED_RADIO_CALIBRATION == 1) */ | ||
| 33 | // | ||
| 34 | // #if (CFG_LPM_LEVEL != 0) | ||
| 35 | // #include "stm32_lpm.h" | ||
| 36 | // #include "stm32_lpm_if.h" | ||
| 37 | // #endif /* (CFG_LPM_LEVEL != 0) */ | ||
| 38 | // | ||
| 39 | // /* USER CODE BEGIN Includes */ | ||
| 40 | // | ||
| 41 | // /* USER CODE END Includes */ | ||
| 42 | // | ||
| 43 | // #define max(a,b) ((a) > (b) ? a : b) | ||
| 44 | // | ||
| 45 | // /* 2.4GHz RADIO ISR callbacks */ | ||
| 46 | // void (*radio_callback)(void) = NULL; | ||
| 47 | // void (*low_isr_callback)(void) = NULL; | ||
| 48 | // | ||
| 49 | // /* RNG handle */ | ||
| 50 | // extern RNG_HandleTypeDef hrng; | ||
| 51 | // | ||
| 52 | // #if (USE_TEMPERATURE_BASED_RADIO_CALIBRATION == 1) | ||
| 53 | // /* Link Layer temperature request from background */ | ||
| 54 | // extern void ll_sys_bg_temperature_measurement(void); | ||
| 55 | // #endif /* (USE_TEMPERATURE_BASED_RADIO_CALIBRATION == 1) */ | ||
| 56 | // | ||
| 57 | // /* Radio critical sections */ | ||
| 58 | // static uint32_t primask_bit = 0; | ||
| 59 | // volatile int32_t prio_high_isr_counter = 0; | ||
| 60 | // volatile int32_t prio_low_isr_counter = 0; | ||
| 61 | // volatile int32_t prio_sys_isr_counter = 0; | ||
| 62 | // volatile int32_t irq_counter = 0; | ||
| 63 | // volatile uint32_t local_basepri_value = 0; | ||
| 64 | // | ||
| 65 | // /* Radio SW low ISR global variable */ | ||
| 66 | // volatile uint8_t radio_sw_low_isr_is_running_high_prio = 0; | ||
| 67 | // | ||
| 68 | // /* Radio bus clock control variables */ | ||
| 69 | // uint8_t AHB5_SwitchedOff = 0; | ||
| 70 | // uint32_t radio_sleep_timer_val = 0; | ||
| 71 | // | ||
| 72 | // /* USER CODE BEGIN LINKLAYER_PLAT 0 */ | ||
| 73 | // | ||
| 74 | // /* USER CODE END LINKLAYER_PLAT 0 */ | ||
| 1 | #![cfg(feature = "wba")] | 75 | #![cfg(feature = "wba")] |
| 2 | #![allow(clippy::missing_safety_doc)] | 76 | #![allow(clippy::missing_safety_doc)] |
| 3 | 77 | ||
| 78 | //! STM32WBA Link Layer platform adaptation layer. | ||
| 79 | //! | ||
| 80 | //! Based on STMicroelectronics original C source `linklayer_plat.c` (2024). | ||
| 81 | |||
| 4 | use core::hint::spin_loop; | 82 | use core::hint::spin_loop; |
| 5 | use core::ptr; | 83 | use core::ptr; |
| 6 | use core::sync::atomic::{AtomicBool, AtomicI32, AtomicPtr, AtomicU32, Ordering}; | 84 | use core::sync::atomic::{AtomicBool, AtomicI32, AtomicPtr, AtomicU32, Ordering}; |
| @@ -200,16 +278,36 @@ pub unsafe fn run_radio_sw_low_isr() { | |||
| 200 | } | 278 | } |
| 201 | } | 279 | } |
| 202 | 280 | ||
| 281 | /// Initialize radio-related clock prerequisites. | ||
| 282 | /// | ||
| 283 | /// Currently this touches the sleep timer to ensure the Link Layer common | ||
| 284 | /// interface is initialized. It does not actively reconfigure clocks. | ||
| 285 | /// | ||
| 286 | /// # Safety | ||
| 287 | /// Called from the vendor Link Layer. Must run in a context where accessing | ||
| 288 | /// the LL common interface is safe. | ||
| 203 | #[unsafe(no_mangle)] | 289 | #[unsafe(no_mangle)] |
| 204 | pub unsafe extern "C" fn LINKLAYER_PLAT_ClockInit() { | 290 | pub unsafe extern "C" fn LINKLAYER_PLAT_ClockInit() { |
| 205 | let _ = link_layer::ll_intf_cmn_get_slptmr_value(); | 291 | let _ = link_layer::ll_intf_cmn_get_slptmr_value(); |
| 206 | } | 292 | } |
| 207 | 293 | ||
| 294 | /// Busy-wait for the requested duration in microseconds. | ||
| 295 | /// | ||
| 296 | /// Blocks the current context until `delay` microseconds have elapsed. | ||
| 297 | /// | ||
| 298 | /// # Safety | ||
| 299 | /// Must be called only in contexts where busy-waiting is acceptable (e.g. no | ||
| 300 | /// hard real-time deadlines are violated). | ||
| 208 | #[unsafe(no_mangle)] | 301 | #[unsafe(no_mangle)] |
| 209 | pub unsafe extern "C" fn LINKLAYER_PLAT_DelayUs(delay: u32) { | 302 | pub unsafe extern "C" fn LINKLAYER_PLAT_DelayUs(delay: u32) { |
| 210 | block_for(Duration::from_micros(u64::from(delay))); | 303 | block_for(Duration::from_micros(u64::from(delay))); |
| 211 | } | 304 | } |
| 212 | 305 | ||
| 306 | /// Assert a condition and panic if it is false. | ||
| 307 | /// | ||
| 308 | /// # Safety | ||
| 309 | /// None beyond general panic considerations; will abort/panic the program if | ||
| 310 | /// `condition == 0`. | ||
| 213 | #[unsafe(no_mangle)] | 311 | #[unsafe(no_mangle)] |
| 214 | pub unsafe extern "C" fn LINKLAYER_PLAT_Assert(condition: u8) { | 312 | pub unsafe extern "C" fn LINKLAYER_PLAT_Assert(condition: u8) { |
| 215 | if condition == 0 { | 313 | if condition == 0 { |
| @@ -217,6 +315,13 @@ pub unsafe extern "C" fn LINKLAYER_PLAT_Assert(condition: u8) { | |||
| 217 | } | 315 | } |
| 218 | } | 316 | } |
| 219 | 317 | ||
| 318 | /// Wait for the AHB5 clock domain to be ready after low-power entry. | ||
| 319 | /// | ||
| 320 | /// If the platform flagged AHB5 as switched off before WFI, this waits until | ||
| 321 | /// the sleep timer ticks, indicating the bus has resumed. | ||
| 322 | /// | ||
| 323 | /// # Safety | ||
| 324 | /// Spins while waiting; must be safe to busy-wait in the calling context. | ||
| 220 | #[unsafe(no_mangle)] | 325 | #[unsafe(no_mangle)] |
| 221 | pub unsafe extern "C" fn LINKLAYER_PLAT_WaitHclkRdy() { | 326 | pub unsafe extern "C" fn LINKLAYER_PLAT_WaitHclkRdy() { |
| 222 | if AHB5_SWITCHED_OFF.swap(false, Ordering::AcqRel) { | 327 | if AHB5_SWITCHED_OFF.swap(false, Ordering::AcqRel) { |
| @@ -227,11 +332,23 @@ pub unsafe extern "C" fn LINKLAYER_PLAT_WaitHclkRdy() { | |||
| 227 | } | 332 | } |
| 228 | } | 333 | } |
| 229 | 334 | ||
| 335 | /// Notify that the system is entering WFI and AHB5 may be turned off depending | ||
| 336 | /// on radio state. | ||
| 337 | /// | ||
| 338 | /// # Safety | ||
| 339 | /// None; this only updates internal state used to resynchronize after WFI. | ||
| 230 | #[unsafe(no_mangle)] | 340 | #[unsafe(no_mangle)] |
| 231 | pub unsafe extern "C" fn LINKLAYER_PLAT_NotifyWFIEnter() { | 341 | pub unsafe extern "C" fn LINKLAYER_PLAT_NotifyWFIEnter() { |
| 232 | AHB5_SWITCHED_OFF.store(true, Ordering::Release); | 342 | AHB5_SWITCHED_OFF.store(true, Ordering::Release); |
| 233 | } | 343 | } |
| 234 | 344 | ||
| 345 | /// Notify that the system exited WFI and capture a reference sleep timer value. | ||
| 346 | /// | ||
| 347 | /// If AHB5 was flagged as switched off on entry, records the current sleep | ||
| 348 | /// timer value for later synchronization in [`LINKLAYER_PLAT_WaitHclkRdy`]. | ||
| 349 | /// | ||
| 350 | /// # Safety | ||
| 351 | /// None; reads a monotonic timer from the LL common interface. | ||
| 235 | #[unsafe(no_mangle)] | 352 | #[unsafe(no_mangle)] |
| 236 | pub unsafe extern "C" fn LINKLAYER_PLAT_NotifyWFIExit() { | 353 | pub unsafe extern "C" fn LINKLAYER_PLAT_NotifyWFIExit() { |
| 237 | if AHB5_SWITCHED_OFF.load(Ordering::Acquire) { | 354 | if AHB5_SWITCHED_OFF.load(Ordering::Acquire) { |
| @@ -240,9 +357,24 @@ pub unsafe extern "C" fn LINKLAYER_PLAT_NotifyWFIExit() { | |||
| 240 | } | 357 | } |
| 241 | } | 358 | } |
| 242 | 359 | ||
| 360 | /// Control the active clock (placeholder). | ||
| 361 | /// | ||
| 362 | /// Currently a no-op. Present for API compatibility with vendor code. | ||
| 363 | /// | ||
| 364 | /// # Safety | ||
| 365 | /// None; function does nothing. | ||
| 243 | #[unsafe(no_mangle)] | 366 | #[unsafe(no_mangle)] |
| 244 | pub unsafe extern "C" fn LINKLAYER_PLAT_AclkCtrl(_enable: u8) {} | 367 | pub unsafe extern "C" fn LINKLAYER_PLAT_AclkCtrl(_enable: u8) {} |
| 245 | 368 | ||
| 369 | /// Fill a buffer with pseudo-random bytes. | ||
| 370 | /// | ||
| 371 | /// This uses a xorshift32 PRNG seeded from the sleep timer and core clock. | ||
| 372 | /// It is not cryptographically secure and is intended only for non-security | ||
| 373 | /// purposes. | ||
| 374 | /// | ||
| 375 | /// # Safety | ||
| 376 | /// - `ptr_rnd` must be valid for writes of `len` bytes. | ||
| 377 | /// - The memory region must not alias mutable references elsewhere. | ||
| 246 | #[unsafe(no_mangle)] | 378 | #[unsafe(no_mangle)] |
| 247 | pub unsafe extern "C" fn LINKLAYER_PLAT_GetRNG(ptr_rnd: *mut u8, len: u32) { | 379 | pub unsafe extern "C" fn LINKLAYER_PLAT_GetRNG(ptr_rnd: *mut u8, len: u32) { |
| 248 | if ptr_rnd.is_null() || len == 0 { | 380 | if ptr_rnd.is_null() || len == 0 { |
| @@ -255,6 +387,14 @@ pub unsafe extern "C" fn LINKLAYER_PLAT_GetRNG(ptr_rnd: *mut u8, len: u32) { | |||
| 255 | } | 387 | } |
| 256 | } | 388 | } |
| 257 | 389 | ||
| 390 | /// Configure the radio high-priority interrupt callback and NVIC state. | ||
| 391 | /// | ||
| 392 | /// When `intr_cb` is `Some`, sets the NVIC priority to | ||
| 393 | /// `RADIO_INTR_PRIO_HIGH` and unmasks the interrupt. Passing `None` disables | ||
| 394 | /// the interrupt. | ||
| 395 | /// | ||
| 396 | /// # Safety | ||
| 397 | /// `intr_cb` must be an ISR-safe function. Alters NVIC state globally. | ||
| 258 | #[unsafe(no_mangle)] | 398 | #[unsafe(no_mangle)] |
| 259 | pub unsafe extern "C" fn LINKLAYER_PLAT_SetupRadioIT(intr_cb: Option<Callback>) { | 399 | pub unsafe extern "C" fn LINKLAYER_PLAT_SetupRadioIT(intr_cb: Option<Callback>) { |
| 260 | store_callback(&RADIO_CALLBACK, intr_cb); | 400 | store_callback(&RADIO_CALLBACK, intr_cb); |
| @@ -267,6 +407,14 @@ pub unsafe extern "C" fn LINKLAYER_PLAT_SetupRadioIT(intr_cb: Option<Callback>) | |||
| 267 | } | 407 | } |
| 268 | } | 408 | } |
| 269 | 409 | ||
| 410 | /// Configure the software low-priority radio interrupt callback and NVIC state. | ||
| 411 | /// | ||
| 412 | /// When `intr_cb` is `Some`, sets the NVIC priority to | ||
| 413 | /// `RADIO_SW_LOW_INTR_PRIO` and unmasks the interrupt. Passing `None` | ||
| 414 | /// disables the interrupt. | ||
| 415 | /// | ||
| 416 | /// # Safety | ||
| 417 | /// `intr_cb` must be ISR-safe. Alters NVIC state globally. | ||
| 270 | #[unsafe(no_mangle)] | 418 | #[unsafe(no_mangle)] |
| 271 | pub unsafe extern "C" fn LINKLAYER_PLAT_SetupSwLowIT(intr_cb: Option<Callback>) { | 419 | pub unsafe extern "C" fn LINKLAYER_PLAT_SetupSwLowIT(intr_cb: Option<Callback>) { |
| 272 | store_callback(&LOW_ISR_CALLBACK, intr_cb); | 420 | store_callback(&LOW_ISR_CALLBACK, intr_cb); |
| @@ -279,6 +427,13 @@ pub unsafe extern "C" fn LINKLAYER_PLAT_SetupSwLowIT(intr_cb: Option<Callback>) | |||
| 279 | } | 427 | } |
| 280 | } | 428 | } |
| 281 | 429 | ||
| 430 | /// Trigger the software low-priority radio interrupt. | ||
| 431 | /// | ||
| 432 | /// If `priority` is non-zero, elevates the interrupt to the low radio priority | ||
| 433 | /// for this trigger or the next run when already active. | ||
| 434 | /// | ||
| 435 | /// # Safety | ||
| 436 | /// Alters NVIC pending and priority state; must be safe for the system. | ||
| 282 | #[unsafe(no_mangle)] | 437 | #[unsafe(no_mangle)] |
| 283 | pub unsafe extern "C" fn LINKLAYER_PLAT_TriggerSwLowIT(priority: u8) { | 438 | pub unsafe extern "C" fn LINKLAYER_PLAT_TriggerSwLowIT(priority: u8) { |
| 284 | let active = nvic_get_active(RADIO_SW_LOW_INTR_NUM); | 439 | let active = nvic_get_active(RADIO_SW_LOW_INTR_NUM); |
| @@ -297,6 +452,13 @@ pub unsafe extern "C" fn LINKLAYER_PLAT_TriggerSwLowIT(priority: u8) { | |||
| 297 | nvic_set_pending(RADIO_SW_LOW_INTR_NUM); | 452 | nvic_set_pending(RADIO_SW_LOW_INTR_NUM); |
| 298 | } | 453 | } |
| 299 | 454 | ||
| 455 | /// Enable interrupts using a reference-counted scheme. | ||
| 456 | /// | ||
| 457 | /// When the internal counter reaches zero, restores the previous PRIMASK | ||
| 458 | /// snapshot and enables or keeps interrupts disabled accordingly. | ||
| 459 | /// | ||
| 460 | /// # Safety | ||
| 461 | /// Must be paired with prior calls to [`LINKLAYER_PLAT_DisableIRQ`]. | ||
| 300 | #[unsafe(no_mangle)] | 462 | #[unsafe(no_mangle)] |
| 301 | pub unsafe extern "C" fn LINKLAYER_PLAT_EnableIRQ() { | 463 | pub unsafe extern "C" fn LINKLAYER_PLAT_EnableIRQ() { |
| 302 | if counter_release(&IRQ_COUNTER) { | 464 | if counter_release(&IRQ_COUNTER) { |
| @@ -309,6 +471,13 @@ pub unsafe extern "C" fn LINKLAYER_PLAT_EnableIRQ() { | |||
| 309 | } | 471 | } |
| 310 | } | 472 | } |
| 311 | 473 | ||
| 474 | /// Disable interrupts using a reference-counted scheme. | ||
| 475 | /// | ||
| 476 | /// Captures the current PRIMASK state on the first disable and then disables | ||
| 477 | /// interrupts. Must be balanced with [`LINKLAYER_PLAT_EnableIRQ`]. | ||
| 478 | /// | ||
| 479 | /// # Safety | ||
| 480 | /// Affects global interrupt state; may impact system timing and ISRs. | ||
| 312 | #[unsafe(no_mangle)] | 481 | #[unsafe(no_mangle)] |
| 313 | pub unsafe extern "C" fn LINKLAYER_PLAT_DisableIRQ() { | 482 | pub unsafe extern "C" fn LINKLAYER_PLAT_DisableIRQ() { |
| 314 | if counter_acquire(&IRQ_COUNTER) { | 483 | if counter_acquire(&IRQ_COUNTER) { |
| @@ -318,6 +487,16 @@ pub unsafe extern "C" fn LINKLAYER_PLAT_DisableIRQ() { | |||
| 318 | cortex_m::interrupt::disable(); | 487 | cortex_m::interrupt::disable(); |
| 319 | } | 488 | } |
| 320 | 489 | ||
| 490 | /// Enable specific Link Layer interrupt groups. | ||
| 491 | /// | ||
| 492 | /// - `LL_HIGH_ISR_ONLY`: Unmask high-priority radio ISR. | ||
| 493 | /// - `LL_LOW_ISR_ONLY`: Unmask software low-priority radio ISR. | ||
| 494 | /// - `SYS_LOW_ISR`: Lower BASEPRI mask to re-enable lower-priority system ISRs. | ||
| 495 | /// | ||
| 496 | /// Uses internal reference counters so multiple disables/enables can be nested. | ||
| 497 | /// | ||
| 498 | /// # Safety | ||
| 499 | /// Alters NVIC and BASEPRI state globally. | ||
| 321 | #[unsafe(no_mangle)] | 500 | #[unsafe(no_mangle)] |
| 322 | pub unsafe extern "C" fn LINKLAYER_PLAT_EnableSpecificIRQ(isr_type: u8) { | 501 | pub unsafe extern "C" fn LINKLAYER_PLAT_EnableSpecificIRQ(isr_type: u8) { |
| 323 | if (isr_type & link_layer::LL_HIGH_ISR_ONLY as u8) != 0 { | 502 | if (isr_type & link_layer::LL_HIGH_ISR_ONLY as u8) != 0 { |
| @@ -340,6 +519,16 @@ pub unsafe extern "C" fn LINKLAYER_PLAT_EnableSpecificIRQ(isr_type: u8) { | |||
| 340 | } | 519 | } |
| 341 | } | 520 | } |
| 342 | 521 | ||
| 522 | /// Disable specific Link Layer interrupt groups. | ||
| 523 | /// | ||
| 524 | /// - `LL_HIGH_ISR_ONLY`: Mask high-priority radio ISR. | ||
| 525 | /// - `LL_LOW_ISR_ONLY`: Mask software low-priority radio ISR. | ||
| 526 | /// - `SYS_LOW_ISR`: Raise BASEPRI to mask system ISRs lower than SW low-priority. | ||
| 527 | /// | ||
| 528 | /// Uses internal reference counters so multiple disables/enables can be nested. | ||
| 529 | /// | ||
| 530 | /// # Safety | ||
| 531 | /// Alters NVIC and BASEPRI state globally. | ||
| 343 | #[unsafe(no_mangle)] | 532 | #[unsafe(no_mangle)] |
| 344 | pub unsafe extern "C" fn LINKLAYER_PLAT_DisableSpecificIRQ(isr_type: u8) { | 533 | pub unsafe extern "C" fn LINKLAYER_PLAT_DisableSpecificIRQ(isr_type: u8) { |
| 345 | if (isr_type & link_layer::LL_HIGH_ISR_ONLY as u8) != 0 { | 534 | if (isr_type & link_layer::LL_HIGH_ISR_ONLY as u8) != 0 { |
| @@ -363,45 +552,107 @@ pub unsafe extern "C" fn LINKLAYER_PLAT_DisableSpecificIRQ(isr_type: u8) { | |||
| 363 | } | 552 | } |
| 364 | } | 553 | } |
| 365 | 554 | ||
| 555 | /// Unmask the radio high-priority interrupt. | ||
| 556 | /// | ||
| 557 | /// # Safety | ||
| 558 | /// Alters NVIC state globally. | ||
| 366 | #[unsafe(no_mangle)] | 559 | #[unsafe(no_mangle)] |
| 367 | pub unsafe extern "C" fn LINKLAYER_PLAT_EnableRadioIT() { | 560 | pub unsafe extern "C" fn LINKLAYER_PLAT_EnableRadioIT() { |
| 368 | nvic_enable(mac::RADIO_INTR_NUM); | 561 | nvic_enable(mac::RADIO_INTR_NUM); |
| 369 | } | 562 | } |
| 370 | 563 | ||
| 564 | /// Mask the radio high-priority interrupt. | ||
| 565 | /// | ||
| 566 | /// # Safety | ||
| 567 | /// Alters NVIC state globally. | ||
| 371 | #[unsafe(no_mangle)] | 568 | #[unsafe(no_mangle)] |
| 372 | pub unsafe extern "C" fn LINKLAYER_PLAT_DisableRadioIT() { | 569 | pub unsafe extern "C" fn LINKLAYER_PLAT_DisableRadioIT() { |
| 373 | nvic_disable(mac::RADIO_INTR_NUM); | 570 | nvic_disable(mac::RADIO_INTR_NUM); |
| 374 | } | 571 | } |
| 375 | 572 | ||
| 573 | /// Notify that a radio activity is starting. | ||
| 574 | /// | ||
| 575 | /// Sets the radio interrupt priority to high and unmasks it. | ||
| 576 | /// | ||
| 577 | /// # Safety | ||
| 578 | /// Alters NVIC state globally. | ||
| 376 | #[unsafe(no_mangle)] | 579 | #[unsafe(no_mangle)] |
| 377 | pub unsafe extern "C" fn LINKLAYER_PLAT_StartRadioEvt() { | 580 | pub unsafe extern "C" fn LINKLAYER_PLAT_StartRadioEvt() { |
| 378 | nvic_set_priority(mac::RADIO_INTR_NUM, pack_priority(mac::RADIO_INTR_PRIO_HIGH)); | 581 | nvic_set_priority(mac::RADIO_INTR_NUM, pack_priority(mac::RADIO_INTR_PRIO_HIGH)); |
| 379 | nvic_enable(mac::RADIO_INTR_NUM); | 582 | nvic_enable(mac::RADIO_INTR_NUM); |
| 380 | } | 583 | } |
| 381 | 584 | ||
| 585 | /// Notify that a radio activity ended. | ||
| 586 | /// | ||
| 587 | /// Lowers the radio interrupt priority to its low setting. | ||
| 588 | /// | ||
| 589 | /// # Safety | ||
| 590 | /// Alters NVIC state globally. | ||
| 382 | #[unsafe(no_mangle)] | 591 | #[unsafe(no_mangle)] |
| 383 | pub unsafe extern "C" fn LINKLAYER_PLAT_StopRadioEvt() { | 592 | pub unsafe extern "C" fn LINKLAYER_PLAT_StopRadioEvt() { |
| 384 | nvic_set_priority(mac::RADIO_INTR_NUM, pack_priority(mac::RADIO_INTR_PRIO_LOW)); | 593 | nvic_set_priority(mac::RADIO_INTR_NUM, pack_priority(mac::RADIO_INTR_PRIO_LOW)); |
| 385 | } | 594 | } |
| 386 | 595 | ||
| 596 | /// Notify that RCO calibration is starting (placeholder). | ||
| 597 | /// | ||
| 598 | /// Currently a no-op. | ||
| 599 | /// | ||
| 600 | /// # Safety | ||
| 601 | /// None. | ||
| 387 | #[unsafe(no_mangle)] | 602 | #[unsafe(no_mangle)] |
| 388 | pub unsafe extern "C" fn LINKLAYER_PLAT_RCOStartClbr() {} | 603 | pub unsafe extern "C" fn LINKLAYER_PLAT_RCOStartClbr() {} |
| 389 | 604 | ||
| 605 | /// Notify that RCO calibration ended (placeholder). | ||
| 606 | /// | ||
| 607 | /// Currently a no-op. | ||
| 608 | /// | ||
| 609 | /// # Safety | ||
| 610 | /// None. | ||
| 390 | #[unsafe(no_mangle)] | 611 | #[unsafe(no_mangle)] |
| 391 | pub unsafe extern "C" fn LINKLAYER_PLAT_RCOStopClbr() {} | 612 | pub unsafe extern "C" fn LINKLAYER_PLAT_RCOStopClbr() {} |
| 392 | 613 | ||
| 614 | /// Request a temperature measurement for radio calibration (placeholder). | ||
| 615 | /// | ||
| 616 | /// Currently a no-op. | ||
| 617 | /// | ||
| 618 | /// # Safety | ||
| 619 | /// None. | ||
| 393 | #[unsafe(no_mangle)] | 620 | #[unsafe(no_mangle)] |
| 394 | pub unsafe extern "C" fn LINKLAYER_PLAT_RequestTemperature() {} | 621 | pub unsafe extern "C" fn LINKLAYER_PLAT_RequestTemperature() {} |
| 395 | 622 | ||
| 623 | /// Notify that PHY calibration is starting (placeholder). | ||
| 624 | /// | ||
| 625 | /// Currently a no-op. | ||
| 626 | /// | ||
| 627 | /// # Safety | ||
| 628 | /// None. | ||
| 396 | #[unsafe(no_mangle)] | 629 | #[unsafe(no_mangle)] |
| 397 | pub unsafe extern "C" fn LINKLAYER_PLAT_PhyStartClbr() {} | 630 | pub unsafe extern "C" fn LINKLAYER_PLAT_PhyStartClbr() {} |
| 398 | 631 | ||
| 632 | /// Notify that PHY calibration ended (placeholder). | ||
| 633 | /// | ||
| 634 | /// Currently a no-op. | ||
| 635 | /// | ||
| 636 | /// # Safety | ||
| 637 | /// None. | ||
| 399 | #[unsafe(no_mangle)] | 638 | #[unsafe(no_mangle)] |
| 400 | pub unsafe extern "C" fn LINKLAYER_PLAT_PhyStopClbr() {} | 639 | pub unsafe extern "C" fn LINKLAYER_PLAT_PhyStopClbr() {} |
| 401 | 640 | ||
| 641 | /// Notify that new Link Layer scheduler timings have been applied (placeholder). | ||
| 642 | /// | ||
| 643 | /// Currently a no-op. | ||
| 644 | /// | ||
| 645 | /// # Safety | ||
| 646 | /// None. | ||
| 402 | #[unsafe(no_mangle)] | 647 | #[unsafe(no_mangle)] |
| 403 | pub unsafe extern "C" fn LINKLAYER_PLAT_SCHLDR_TIMING_UPDATE_NOT(_timings: *const link_layer::Evnt_timing_t) {} | 648 | pub unsafe extern "C" fn LINKLAYER_PLAT_SCHLDR_TIMING_UPDATE_NOT(_timings: *const link_layer::Evnt_timing_t) {} |
| 404 | 649 | ||
| 650 | /// Return the STMicroelectronics Bluetooth SIG Company Identifier. | ||
| 651 | /// | ||
| 652 | /// Value: `0x0030`. | ||
| 653 | /// | ||
| 654 | /// # Safety | ||
| 655 | /// None. | ||
| 405 | #[unsafe(no_mangle)] | 656 | #[unsafe(no_mangle)] |
| 406 | pub unsafe extern "C" fn LINKLAYER_PLAT_GetSTCompanyID() -> u32 { | 657 | pub unsafe extern "C" fn LINKLAYER_PLAT_GetSTCompanyID() -> u32 { |
| 407 | // STMicroelectronics Bluetooth SIG Company Identifier | 658 | // STMicroelectronics Bluetooth SIG Company Identifier |
| @@ -409,6 +660,13 @@ pub unsafe extern "C" fn LINKLAYER_PLAT_GetSTCompanyID() -> u32 { | |||
| 409 | 0x0030 | 660 | 0x0030 |
| 410 | } | 661 | } |
| 411 | 662 | ||
| 663 | /// Return the lower 32 bits of the STM32 unique 96-bit device identifier. | ||
| 664 | /// | ||
| 665 | /// Note: This may differ from the ST-defined UDN encoding found in some device | ||
| 666 | /// registers/documents; it returns the first word of the unique ID. | ||
| 667 | /// | ||
| 668 | /// # Safety | ||
| 669 | /// None. | ||
| 412 | #[unsafe(no_mangle)] | 670 | #[unsafe(no_mangle)] |
| 413 | pub unsafe extern "C" fn LINKLAYER_PLAT_GetUDN() -> u32 { | 671 | pub unsafe extern "C" fn LINKLAYER_PLAT_GetUDN() -> u32 { |
| 414 | // Read the first 32 bits of the STM32 unique 96-bit ID | 672 | // Read the first 32 bits of the STM32 unique 96-bit ID |
