diff options
Diffstat (limited to 'embassy-stm32-wpan/src/wba/linklayer_plat.rs')
| -rw-r--r-- | embassy-stm32-wpan/src/wba/linklayer_plat.rs | 913 |
1 files changed, 913 insertions, 0 deletions
diff --git a/embassy-stm32-wpan/src/wba/linklayer_plat.rs b/embassy-stm32-wpan/src/wba/linklayer_plat.rs new file mode 100644 index 000000000..108e84efe --- /dev/null +++ b/embassy-stm32-wpan/src/wba/linklayer_plat.rs | |||
| @@ -0,0 +1,913 @@ | |||
| 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 */ | ||
| 75 | #![cfg(feature = "wba")] | ||
| 76 | #![allow(clippy::missing_safety_doc)] | ||
| 77 | |||
| 78 | use core::hint::spin_loop; | ||
| 79 | use core::ptr; | ||
| 80 | use core::sync::atomic::{AtomicBool, AtomicI32, AtomicPtr, AtomicU32, Ordering}; | ||
| 81 | |||
| 82 | use cortex_m::asm::{dsb, isb}; | ||
| 83 | use cortex_m::interrupt::InterruptNumber; | ||
| 84 | use cortex_m::peripheral::NVIC; | ||
| 85 | use cortex_m::register::basepri; | ||
| 86 | use critical_section; | ||
| 87 | #[cfg(feature = "defmt")] | ||
| 88 | use defmt::trace; | ||
| 89 | use embassy_stm32::NVIC_PRIO_BITS; | ||
| 90 | use embassy_time::{Duration, block_for}; | ||
| 91 | |||
| 92 | use super::bindings::{link_layer, mac}; | ||
| 93 | |||
| 94 | // Missing constant from stm32-bindings - RADIO_SW_LOW interrupt number | ||
| 95 | // For STM32WBA, this is typically RADIO_IRQ_BUSY (interrupt 43) | ||
| 96 | const RADIO_SW_LOW_INTR_NUM: u32 = 43; | ||
| 97 | |||
| 98 | type Callback = unsafe extern "C" fn(); | ||
| 99 | |||
| 100 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||
| 101 | #[repr(transparent)] | ||
| 102 | struct RawInterrupt(u16); | ||
| 103 | |||
| 104 | impl RawInterrupt { | ||
| 105 | #[inline(always)] | ||
| 106 | fn new(irq: u32) -> Self { | ||
| 107 | debug_assert!(irq <= u16::MAX as u32); | ||
| 108 | Self(irq as u16) | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | impl From<u32> for RawInterrupt { | ||
| 113 | #[inline(always)] | ||
| 114 | fn from(value: u32) -> Self { | ||
| 115 | Self::new(value) | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | unsafe impl InterruptNumber for RawInterrupt { | ||
| 120 | fn number(self) -> u16 { | ||
| 121 | self.0 | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | static RADIO_CALLBACK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); | ||
| 126 | static LOW_ISR_CALLBACK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); | ||
| 127 | |||
| 128 | static IRQ_COUNTER: AtomicI32 = AtomicI32::new(0); | ||
| 129 | |||
| 130 | static PRIO_HIGH_ISR_COUNTER: AtomicI32 = AtomicI32::new(0); | ||
| 131 | static PRIO_LOW_ISR_COUNTER: AtomicI32 = AtomicI32::new(0); | ||
| 132 | static PRIO_SYS_ISR_COUNTER: AtomicI32 = AtomicI32::new(0); | ||
| 133 | static LOCAL_BASEPRI_VALUE: AtomicU32 = AtomicU32::new(0); | ||
| 134 | |||
| 135 | static RADIO_SW_LOW_ISR_RUNNING_HIGH_PRIO: AtomicBool = AtomicBool::new(false); | ||
| 136 | static AHB5_SWITCHED_OFF: AtomicBool = AtomicBool::new(false); | ||
| 137 | static RADIO_SLEEP_TIMER_VAL: AtomicU32 = AtomicU32::new(0); | ||
| 138 | |||
| 139 | static PRNG_STATE: AtomicU32 = AtomicU32::new(0); | ||
| 140 | static PRNG_INIT: AtomicBool = AtomicBool::new(false); | ||
| 141 | |||
| 142 | // Critical-section restore token for IRQ enable/disable pairing. | ||
| 143 | // Only written when the IRQ disable counter transitions 0->1, and consumed when it transitions 1->0. | ||
| 144 | static mut CS_RESTORE_STATE: Option<critical_section::RestoreState> = None; | ||
| 145 | |||
| 146 | unsafe extern "C" { | ||
| 147 | static SystemCoreClock: u32; | ||
| 148 | } | ||
| 149 | |||
| 150 | #[inline(always)] | ||
| 151 | fn read_system_core_clock() -> u32 { | ||
| 152 | unsafe { ptr::read_volatile(&SystemCoreClock) } | ||
| 153 | } | ||
| 154 | |||
| 155 | #[inline(always)] | ||
| 156 | fn store_callback(slot: &AtomicPtr<()>, cb: Option<Callback>) { | ||
| 157 | let ptr = cb.map_or(ptr::null_mut(), |f| f as *mut ()); | ||
| 158 | slot.store(ptr, Ordering::Release); | ||
| 159 | } | ||
| 160 | |||
| 161 | #[inline(always)] | ||
| 162 | fn load_callback(slot: &AtomicPtr<()>) -> Option<Callback> { | ||
| 163 | let ptr = slot.load(Ordering::Acquire); | ||
| 164 | if ptr.is_null() { | ||
| 165 | None | ||
| 166 | } else { | ||
| 167 | Some(unsafe { core::mem::transmute::<*mut (), Callback>(ptr) }) | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | #[inline(always)] | ||
| 172 | fn priority_shift() -> u8 { | ||
| 173 | 8 - NVIC_PRIO_BITS as u8 | ||
| 174 | } | ||
| 175 | |||
| 176 | fn pack_priority(raw: u32) -> u8 { | ||
| 177 | let shift = priority_shift(); | ||
| 178 | let priority_bits = NVIC_PRIO_BITS as u32; | ||
| 179 | let mask = if priority_bits >= 32 { | ||
| 180 | u32::MAX | ||
| 181 | } else { | ||
| 182 | (1u32 << priority_bits) - 1 | ||
| 183 | }; | ||
| 184 | let clamped = raw & mask; | ||
| 185 | (clamped << u32::from(shift)) as u8 | ||
| 186 | } | ||
| 187 | |||
| 188 | #[inline(always)] | ||
| 189 | fn counter_release(counter: &AtomicI32) -> bool { | ||
| 190 | counter.fetch_sub(1, Ordering::SeqCst) <= 1 | ||
| 191 | } | ||
| 192 | |||
| 193 | #[inline(always)] | ||
| 194 | fn counter_acquire(counter: &AtomicI32) -> bool { | ||
| 195 | counter.fetch_add(1, Ordering::SeqCst) == 0 | ||
| 196 | } | ||
| 197 | |||
| 198 | unsafe fn nvic_enable(irq: u32) { | ||
| 199 | NVIC::unmask(RawInterrupt::new(irq)); | ||
| 200 | dsb(); | ||
| 201 | isb(); | ||
| 202 | } | ||
| 203 | |||
| 204 | unsafe fn nvic_disable(irq: u32) { | ||
| 205 | NVIC::mask(RawInterrupt::new(irq)); | ||
| 206 | dsb(); | ||
| 207 | isb(); | ||
| 208 | } | ||
| 209 | |||
| 210 | unsafe fn nvic_set_pending(irq: u32) { | ||
| 211 | NVIC::pend(RawInterrupt::new(irq)); | ||
| 212 | dsb(); | ||
| 213 | isb(); | ||
| 214 | } | ||
| 215 | |||
| 216 | unsafe fn nvic_get_active(irq: u32) -> bool { | ||
| 217 | NVIC::is_active(RawInterrupt::new(irq)) | ||
| 218 | } | ||
| 219 | |||
| 220 | unsafe fn nvic_set_priority(irq: u32, priority: u8) { | ||
| 221 | // STM32WBA is ARMv8-M, which uses byte-accessible IPR registers | ||
| 222 | let nvic = &*NVIC::PTR; | ||
| 223 | nvic.ipr[irq as usize].write(priority); | ||
| 224 | |||
| 225 | dsb(); | ||
| 226 | isb(); | ||
| 227 | } | ||
| 228 | |||
| 229 | #[inline(always)] | ||
| 230 | fn set_basepri_max(value: u8) { | ||
| 231 | unsafe { | ||
| 232 | if basepri::read() < value { | ||
| 233 | basepri::write(value); | ||
| 234 | } | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 238 | fn prng_next() -> u32 { | ||
| 239 | #[inline] | ||
| 240 | fn xorshift(mut x: u32) -> u32 { | ||
| 241 | x ^= x << 13; | ||
| 242 | x ^= x >> 17; | ||
| 243 | x ^= x << 5; | ||
| 244 | x | ||
| 245 | } | ||
| 246 | |||
| 247 | if !PRNG_INIT.load(Ordering::Acquire) { | ||
| 248 | let seed = unsafe { | ||
| 249 | let timer = link_layer::ll_intf_cmn_get_slptmr_value(); | ||
| 250 | let core_clock = read_system_core_clock(); | ||
| 251 | timer ^ core_clock ^ 0x6C8E_9CF5 | ||
| 252 | }; | ||
| 253 | PRNG_STATE.store(seed, Ordering::Relaxed); | ||
| 254 | PRNG_INIT.store(true, Ordering::Release); | ||
| 255 | } | ||
| 256 | |||
| 257 | let mut current = PRNG_STATE.load(Ordering::Relaxed); | ||
| 258 | loop { | ||
| 259 | let next = xorshift(current); | ||
| 260 | match PRNG_STATE.compare_exchange_weak(current, next, Ordering::AcqRel, Ordering::Relaxed) { | ||
| 261 | Ok(_) => return next, | ||
| 262 | Err(v) => current = v, | ||
| 263 | } | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | pub unsafe fn run_radio_high_isr() { | ||
| 268 | if let Some(cb) = load_callback(&RADIO_CALLBACK) { | ||
| 269 | cb(); | ||
| 270 | } | ||
| 271 | } | ||
| 272 | |||
| 273 | pub unsafe fn run_radio_sw_low_isr() { | ||
| 274 | if let Some(cb) = load_callback(&LOW_ISR_CALLBACK) { | ||
| 275 | cb(); | ||
| 276 | } | ||
| 277 | |||
| 278 | if RADIO_SW_LOW_ISR_RUNNING_HIGH_PRIO.swap(false, Ordering::AcqRel) { | ||
| 279 | nvic_set_priority(RADIO_SW_LOW_INTR_NUM, pack_priority(mac::RADIO_SW_LOW_INTR_PRIO)); | ||
| 280 | } | ||
| 281 | } | ||
| 282 | |||
| 283 | // /** | ||
| 284 | // * @brief Configure the necessary clock sources for the radio. | ||
| 285 | // * @param None | ||
| 286 | // * @retval None | ||
| 287 | // */ | ||
| 288 | #[unsafe(no_mangle)] | ||
| 289 | pub unsafe extern "C" fn LINKLAYER_PLAT_ClockInit() { | ||
| 290 | // uint32_t linklayer_slp_clk_src = LL_RCC_RADIOSLEEPSOURCE_NONE; | ||
| 291 | // | ||
| 292 | // /* Get the Link Layer sleep timer clock source */ | ||
| 293 | // linklayer_slp_clk_src = LL_RCC_RADIO_GetSleepTimerClockSource(); | ||
| 294 | // if(linklayer_slp_clk_src == LL_RCC_RADIOSLEEPSOURCE_NONE) | ||
| 295 | // { | ||
| 296 | // /* If there is no clock source defined, should be selected before */ | ||
| 297 | // assert_param(0); | ||
| 298 | // } | ||
| 299 | // | ||
| 300 | // /* Enable AHB5ENR peripheral clock (bus CLK) */ | ||
| 301 | // __HAL_RCC_RADIO_CLK_ENABLE(); | ||
| 302 | trace!("LINKLAYER_PLAT_ClockInit: get_slptmr_value"); | ||
| 303 | let _ = link_layer::ll_intf_cmn_get_slptmr_value(); | ||
| 304 | } | ||
| 305 | |||
| 306 | // /** | ||
| 307 | // * @brief Link Layer active waiting loop. | ||
| 308 | // * @param delay: delay in us | ||
| 309 | // * @retval None | ||
| 310 | // */ | ||
| 311 | #[unsafe(no_mangle)] | ||
| 312 | pub unsafe extern "C" fn LINKLAYER_PLAT_DelayUs(delay: u32) { | ||
| 313 | // static uint8_t lock = 0; | ||
| 314 | // uint32_t t0; | ||
| 315 | // uint32_t primask_bit; | ||
| 316 | // | ||
| 317 | // /* Enter critical section */ | ||
| 318 | // primask_bit= __get_PRIMASK(); | ||
| 319 | // __disable_irq(); | ||
| 320 | // | ||
| 321 | // if (lock == 0U) | ||
| 322 | // { | ||
| 323 | // /* Initialize counter */ | ||
| 324 | // /* Reset cycle counter to prevent overflow | ||
| 325 | // As a us counter, it is assumed than even with re-entrancy, | ||
| 326 | // overflow will never happen before re-initializing this counter */ | ||
| 327 | // DWT->CYCCNT = 0U; | ||
| 328 | // /* Enable DWT by safety but should be useless (as already set) */ | ||
| 329 | // SET_BIT(DCB->DEMCR, DCB_DEMCR_TRCENA_Msk); | ||
| 330 | // /* Enable counter */ | ||
| 331 | // SET_BIT(DWT->CTRL, DWT_CTRL_CYCCNTENA_Msk); | ||
| 332 | // } | ||
| 333 | // /* Increment 're-entrance' counter */ | ||
| 334 | // lock++; | ||
| 335 | // /* Get starting time stamp */ | ||
| 336 | // t0 = DWT->CYCCNT; | ||
| 337 | // /* Exit critical section */ | ||
| 338 | // __set_PRIMASK(primask_bit); | ||
| 339 | // | ||
| 340 | // /* Turn us into cycles */ | ||
| 341 | // delay = delay * (SystemCoreClock / 1000000U); | ||
| 342 | // delay += t0; | ||
| 343 | // | ||
| 344 | // /* Busy waiting loop */ | ||
| 345 | // while (DWT->CYCCNT < delay) | ||
| 346 | // { | ||
| 347 | // }; | ||
| 348 | // | ||
| 349 | // /* Enter critical section */ | ||
| 350 | // primask_bit= __get_PRIMASK(); | ||
| 351 | // __disable_irq(); | ||
| 352 | // if (lock == 1U) | ||
| 353 | // { | ||
| 354 | // /* Disable counter */ | ||
| 355 | // CLEAR_BIT(DWT->CTRL, DWT_CTRL_CYCCNTENA_Msk); | ||
| 356 | // } | ||
| 357 | // /* Decrement 're-entrance' counter */ | ||
| 358 | // lock--; | ||
| 359 | // /* Exit critical section */ | ||
| 360 | // __set_PRIMASK(primask_bit); | ||
| 361 | // | ||
| 362 | trace!("LINKLAYER_PLAT_DelayUs: delay={}", delay); | ||
| 363 | block_for(Duration::from_micros(u64::from(delay))); | ||
| 364 | } | ||
| 365 | |||
| 366 | // /** | ||
| 367 | // * @brief Link Layer assertion API | ||
| 368 | // * @param condition: conditional statement to be checked. | ||
| 369 | // * @retval None | ||
| 370 | // */ | ||
| 371 | #[unsafe(no_mangle)] | ||
| 372 | pub unsafe extern "C" fn LINKLAYER_PLAT_Assert(condition: u8) { | ||
| 373 | if condition == 0 { | ||
| 374 | panic!("LINKLAYER_PLAT assertion failed"); | ||
| 375 | } | ||
| 376 | } | ||
| 377 | |||
| 378 | // /** | ||
| 379 | // * @brief Enable/disable the Link Layer active clock (baseband clock). | ||
| 380 | // * @param enable: boolean value to enable (1) or disable (0) the clock. | ||
| 381 | // * @retval None | ||
| 382 | // */ | ||
| 383 | #[unsafe(no_mangle)] | ||
| 384 | pub unsafe extern "C" fn LINKLAYER_PLAT_WaitHclkRdy() { | ||
| 385 | trace!("LINKLAYER_PLAT_WaitHclkRdy"); | ||
| 386 | if AHB5_SWITCHED_OFF.swap(false, Ordering::AcqRel) { | ||
| 387 | let reference = RADIO_SLEEP_TIMER_VAL.load(Ordering::Acquire); | ||
| 388 | trace!("LINKLAYER_PLAT_WaitHclkRdy: reference={}", reference); | ||
| 389 | while reference == link_layer::ll_intf_cmn_get_slptmr_value() { | ||
| 390 | spin_loop(); | ||
| 391 | } | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 395 | // /** | ||
| 396 | // * @brief Notify the Link Layer platform layer the system will enter in WFI | ||
| 397 | // * and AHB5 clock may be turned of regarding the 2.4Ghz radio state. | ||
| 398 | // * @param None | ||
| 399 | // * @retval None | ||
| 400 | // */ | ||
| 401 | #[unsafe(no_mangle)] | ||
| 402 | pub unsafe extern "C" fn LINKLAYER_PLAT_NotifyWFIEnter() { | ||
| 403 | // /* Check if Radio state will allow the AHB5 clock to be cut */ | ||
| 404 | // | ||
| 405 | // /* AHB5 clock will be cut in the following cases: | ||
| 406 | // * - 2.4GHz radio is not in ACTIVE mode (in SLEEP or DEEPSLEEP mode). | ||
| 407 | // * - RADIOSMEN and STRADIOCLKON bits are at 0. | ||
| 408 | // */ | ||
| 409 | // if((LL_PWR_GetRadioMode() != LL_PWR_RADIO_ACTIVE_MODE) || | ||
| 410 | // ((__HAL_RCC_RADIO_IS_CLK_SLEEP_ENABLED() == 0) && (LL_RCC_RADIO_IsEnabledSleepTimerClock() == 0))) | ||
| 411 | // { | ||
| 412 | // AHB5_SwitchedOff = 1; | ||
| 413 | // } | ||
| 414 | trace!("LINKLAYER_PLAT_NotifyWFIEnter"); | ||
| 415 | AHB5_SWITCHED_OFF.store(true, Ordering::Release); | ||
| 416 | } | ||
| 417 | |||
| 418 | // /** | ||
| 419 | // * @brief Notify the Link Layer platform layer the system exited WFI and AHB5 | ||
| 420 | // * clock may be resynchronized as is may have been turned of during | ||
| 421 | // * low power mode entry. | ||
| 422 | // * @param None | ||
| 423 | // * @retval None | ||
| 424 | // */ | ||
| 425 | #[unsafe(no_mangle)] | ||
| 426 | pub unsafe extern "C" fn LINKLAYER_PLAT_NotifyWFIExit() { | ||
| 427 | trace!("LINKLAYER_PLAT_NotifyWFIExit"); | ||
| 428 | // /* Check if AHB5 clock has been turned of and needs resynchronisation */ | ||
| 429 | if AHB5_SWITCHED_OFF.load(Ordering::Acquire) { | ||
| 430 | // /* Read sleep register as earlier as possible */ | ||
| 431 | let value = link_layer::ll_intf_cmn_get_slptmr_value(); | ||
| 432 | RADIO_SLEEP_TIMER_VAL.store(value, Ordering::Release); | ||
| 433 | } | ||
| 434 | } | ||
| 435 | |||
| 436 | // /** | ||
| 437 | // * @brief Active wait on bus clock readiness. | ||
| 438 | // * @param None | ||
| 439 | // * @retval None | ||
| 440 | // */ | ||
| 441 | #[unsafe(no_mangle)] | ||
| 442 | pub unsafe extern "C" fn LINKLAYER_PLAT_AclkCtrl(_enable: u8) { | ||
| 443 | trace!("LINKLAYER_PLAT_AclkCtrl: enable={}", _enable); | ||
| 444 | if _enable != 0 { | ||
| 445 | // #if (CFG_SCM_SUPPORTED == 1) | ||
| 446 | // /* SCM HSE BEGIN */ | ||
| 447 | // /* Polling on HSE32 activation */ | ||
| 448 | // SCM_HSE_WaitUntilReady(); | ||
| 449 | // /* Enable RADIO baseband clock (active CLK) */ | ||
| 450 | // HAL_RCCEx_EnableRadioBBClock(); | ||
| 451 | // /* SCM HSE END */ | ||
| 452 | // #else | ||
| 453 | // /* Enable RADIO baseband clock (active CLK) */ | ||
| 454 | // HAL_RCCEx_EnableRadioBBClock(); | ||
| 455 | // /* Polling on HSE32 activation */ | ||
| 456 | // while ( LL_RCC_HSE_IsReady() == 0); | ||
| 457 | // #endif /* CFG_SCM_SUPPORTED */ | ||
| 458 | // NOTE: Add a proper assertion once a typed `Radio` peripheral exists in embassy-stm32 | ||
| 459 | // that exposes the baseband clock enable status via RCC. | ||
| 460 | } else { | ||
| 461 | // /* Disable RADIO baseband clock (active CLK) */ | ||
| 462 | // HAL_RCCEx_DisableRadioBBClock(); | ||
| 463 | } | ||
| 464 | } | ||
| 465 | |||
| 466 | // /** | ||
| 467 | // * @brief Link Layer RNG request. | ||
| 468 | // * @param ptr_rnd: pointer to the variable that hosts the number. | ||
| 469 | // * @param len: number of byte of anthropy to get. | ||
| 470 | // * @retval None | ||
| 471 | // */ | ||
| 472 | #[unsafe(no_mangle)] | ||
| 473 | pub unsafe extern "C" fn LINKLAYER_PLAT_GetRNG(ptr_rnd: *mut u8, len: u32) { | ||
| 474 | // uint32_t nb_remaining_rng = len; | ||
| 475 | // uint32_t generated_rng; | ||
| 476 | // | ||
| 477 | // /* Get the requested RNGs (4 bytes by 4bytes) */ | ||
| 478 | // while(nb_remaining_rng >= 4) | ||
| 479 | // { | ||
| 480 | // generated_rng = 0; | ||
| 481 | // HW_RNG_Get(1, &generated_rng); | ||
| 482 | // memcpy((ptr_rnd+(len-nb_remaining_rng)), &generated_rng, 4); | ||
| 483 | // nb_remaining_rng -=4; | ||
| 484 | // } | ||
| 485 | // | ||
| 486 | // /* Get the remaining number of RNGs */ | ||
| 487 | // if(nb_remaining_rng>0){ | ||
| 488 | // generated_rng = 0; | ||
| 489 | // HW_RNG_Get(1, &generated_rng); | ||
| 490 | // memcpy((ptr_rnd+(len-nb_remaining_rng)), &generated_rng, nb_remaining_rng); | ||
| 491 | // } | ||
| 492 | trace!("LINKLAYER_PLAT_GetRNG: ptr_rnd={:?}, len={}", ptr_rnd, len); | ||
| 493 | if ptr_rnd.is_null() || len == 0 { | ||
| 494 | return; | ||
| 495 | } | ||
| 496 | |||
| 497 | for i in 0..len { | ||
| 498 | let byte = (prng_next() >> ((i & 3) * 8)) as u8; | ||
| 499 | ptr::write_volatile(ptr_rnd.add(i as usize), byte); | ||
| 500 | } | ||
| 501 | } | ||
| 502 | |||
| 503 | // /** | ||
| 504 | // * @brief Initialize Link Layer radio high priority interrupt. | ||
| 505 | // * @param intr_cb: function pointer to assign for the radio high priority ISR routine. | ||
| 506 | // * @retval None | ||
| 507 | // */ | ||
| 508 | #[unsafe(no_mangle)] | ||
| 509 | pub unsafe extern "C" fn LINKLAYER_PLAT_SetupRadioIT(intr_cb: Option<Callback>) { | ||
| 510 | trace!("LINKLAYER_PLAT_SetupRadioIT: intr_cb={:?}", intr_cb); | ||
| 511 | store_callback(&RADIO_CALLBACK, intr_cb); | ||
| 512 | |||
| 513 | if intr_cb.is_some() { | ||
| 514 | nvic_set_priority(mac::RADIO_INTR_NUM, pack_priority(mac::RADIO_INTR_PRIO_HIGH)); | ||
| 515 | nvic_enable(mac::RADIO_INTR_NUM); | ||
| 516 | } else { | ||
| 517 | nvic_disable(mac::RADIO_INTR_NUM); | ||
| 518 | } | ||
| 519 | } | ||
| 520 | |||
| 521 | // /** | ||
| 522 | // * @brief Initialize Link Layer SW low priority interrupt. | ||
| 523 | // * @param intr_cb: function pointer to assign for the SW low priority ISR routine. | ||
| 524 | // * @retval None | ||
| 525 | // */ | ||
| 526 | #[unsafe(no_mangle)] | ||
| 527 | pub unsafe extern "C" fn LINKLAYER_PLAT_SetupSwLowIT(intr_cb: Option<Callback>) { | ||
| 528 | trace!("LINKLAYER_PLAT_SetupSwLowIT: intr_cb={:?}", intr_cb); | ||
| 529 | store_callback(&LOW_ISR_CALLBACK, intr_cb); | ||
| 530 | |||
| 531 | if intr_cb.is_some() { | ||
| 532 | nvic_set_priority(RADIO_SW_LOW_INTR_NUM, pack_priority(mac::RADIO_SW_LOW_INTR_PRIO)); | ||
| 533 | nvic_enable(RADIO_SW_LOW_INTR_NUM); | ||
| 534 | } else { | ||
| 535 | nvic_disable(RADIO_SW_LOW_INTR_NUM); | ||
| 536 | } | ||
| 537 | } | ||
| 538 | |||
| 539 | // /** | ||
| 540 | // * @brief Trigger the link layer SW low interrupt. | ||
| 541 | // * @param None | ||
| 542 | // * @retval None | ||
| 543 | // */ | ||
| 544 | #[unsafe(no_mangle)] | ||
| 545 | pub unsafe extern "C" fn LINKLAYER_PLAT_TriggerSwLowIT(priority: u8) { | ||
| 546 | trace!("LINKLAYER_PLAT_TriggerSwLowIT: priority={}", priority); | ||
| 547 | let active = nvic_get_active(RADIO_SW_LOW_INTR_NUM); | ||
| 548 | |||
| 549 | // /* Check if a SW low interrupt as already been raised. | ||
| 550 | // * Nested call far radio low isr are not supported | ||
| 551 | // **/ | ||
| 552 | if !active { | ||
| 553 | let prio = if priority == 0 { | ||
| 554 | // /* No nested SW low ISR, default behavior */ | ||
| 555 | pack_priority(mac::RADIO_SW_LOW_INTR_PRIO) | ||
| 556 | } else { | ||
| 557 | pack_priority(mac::RADIO_INTR_PRIO_LOW) | ||
| 558 | }; | ||
| 559 | nvic_set_priority(RADIO_SW_LOW_INTR_NUM, prio); | ||
| 560 | } else if priority != 0 { | ||
| 561 | // /* Nested call detected */ | ||
| 562 | // /* No change for SW radio low interrupt priority for the moment */ | ||
| 563 | // | ||
| 564 | // if(priority != 0) | ||
| 565 | // { | ||
| 566 | // /* At the end of current SW radio low ISR, this pending SW low interrupt | ||
| 567 | // * will run with RADIO_INTR_PRIO_LOW priority | ||
| 568 | // **/ | ||
| 569 | // radio_sw_low_isr_is_running_high_prio = 1; | ||
| 570 | // } | ||
| 571 | RADIO_SW_LOW_ISR_RUNNING_HIGH_PRIO.store(true, Ordering::Release); | ||
| 572 | } | ||
| 573 | |||
| 574 | nvic_set_pending(RADIO_SW_LOW_INTR_NUM); | ||
| 575 | } | ||
| 576 | |||
| 577 | // /** | ||
| 578 | // * @brief Enable interrupts. | ||
| 579 | // * @param None | ||
| 580 | // * @retval None | ||
| 581 | // */ | ||
| 582 | #[unsafe(no_mangle)] | ||
| 583 | pub unsafe extern "C" fn LINKLAYER_PLAT_EnableIRQ() { | ||
| 584 | trace!("LINKLAYER_PLAT_EnableIRQ"); | ||
| 585 | // irq_counter = max(0,irq_counter-1); | ||
| 586 | // | ||
| 587 | // if(irq_counter == 0) | ||
| 588 | // { | ||
| 589 | // /* When irq_counter reaches 0, restore primask bit */ | ||
| 590 | // __set_PRIMASK(primask_bit); | ||
| 591 | // } | ||
| 592 | if counter_release(&IRQ_COUNTER) { | ||
| 593 | // When the counter reaches zero, restore prior interrupt state using the captured token. | ||
| 594 | if let Some(token) = CS_RESTORE_STATE.take() { | ||
| 595 | critical_section::release(token); | ||
| 596 | } | ||
| 597 | } | ||
| 598 | } | ||
| 599 | |||
| 600 | // /** | ||
| 601 | // * @brief Disable interrupts. | ||
| 602 | // * @param None | ||
| 603 | // * @retval None | ||
| 604 | // */ | ||
| 605 | #[unsafe(no_mangle)] | ||
| 606 | pub unsafe extern "C" fn LINKLAYER_PLAT_DisableIRQ() { | ||
| 607 | trace!("LINKLAYER_PLAT_DisableIRQ"); | ||
| 608 | // if(irq_counter == 0) | ||
| 609 | // { | ||
| 610 | // /* Save primask bit at first interrupt disablement */ | ||
| 611 | // primask_bit= __get_PRIMASK(); | ||
| 612 | // } | ||
| 613 | // __disable_irq(); | ||
| 614 | // irq_counter ++; | ||
| 615 | if counter_acquire(&IRQ_COUNTER) { | ||
| 616 | // Capture and disable using critical-section API on first disable. | ||
| 617 | CS_RESTORE_STATE = Some(critical_section::acquire()); | ||
| 618 | } | ||
| 619 | } | ||
| 620 | |||
| 621 | // /** | ||
| 622 | // * @brief Enable specific interrupt group. | ||
| 623 | // * @param isr_type: mask for interrupt group to enable. | ||
| 624 | // * This parameter can be one of the following: | ||
| 625 | // * @arg LL_HIGH_ISR_ONLY: enable link layer high priority ISR. | ||
| 626 | // * @arg LL_LOW_ISR_ONLY: enable link layer SW low priority ISR. | ||
| 627 | // * @arg SYS_LOW_ISR: mask interrupts for all the other system ISR with | ||
| 628 | // * lower priority that link layer SW low interrupt. | ||
| 629 | // * @retval None | ||
| 630 | // */ | ||
| 631 | #[unsafe(no_mangle)] | ||
| 632 | pub unsafe extern "C" fn LINKLAYER_PLAT_EnableSpecificIRQ(isr_type: u8) { | ||
| 633 | trace!("LINKLAYER_PLAT_EnableSpecificIRQ: isr_type={}", isr_type); | ||
| 634 | // if( (isr_type & LL_HIGH_ISR_ONLY) != 0 ) | ||
| 635 | // { | ||
| 636 | // prio_high_isr_counter--; | ||
| 637 | // if(prio_high_isr_counter == 0) | ||
| 638 | // { | ||
| 639 | // /* When specific counter for link layer high ISR reaches 0, interrupt is enabled */ | ||
| 640 | // HAL_NVIC_EnableIRQ(RADIO_INTR_NUM); | ||
| 641 | // /* USER CODE BEGIN LINKLAYER_PLAT_EnableSpecificIRQ_1 */ | ||
| 642 | // | ||
| 643 | // /* USER CODE END LINKLAYER_PLAT_EnableSpecificIRQ_1 */ | ||
| 644 | // } | ||
| 645 | // } | ||
| 646 | // | ||
| 647 | // if( (isr_type & LL_LOW_ISR_ONLY) != 0 ) | ||
| 648 | // { | ||
| 649 | // prio_low_isr_counter--; | ||
| 650 | // if(prio_low_isr_counter == 0) | ||
| 651 | // { | ||
| 652 | // /* When specific counter for link layer SW low ISR reaches 0, interrupt is enabled */ | ||
| 653 | // HAL_NVIC_EnableIRQ(RADIO_SW_LOW_INTR_NUM); | ||
| 654 | // } | ||
| 655 | // | ||
| 656 | // } | ||
| 657 | // | ||
| 658 | // if( (isr_type & SYS_LOW_ISR) != 0 ) | ||
| 659 | // { | ||
| 660 | // prio_sys_isr_counter--; | ||
| 661 | // if(prio_sys_isr_counter == 0) | ||
| 662 | // { | ||
| 663 | // /* Restore basepri value */ | ||
| 664 | // __set_BASEPRI(local_basepri_value); | ||
| 665 | // } | ||
| 666 | // } | ||
| 667 | if (isr_type & link_layer::LL_HIGH_ISR_ONLY as u8) != 0 { | ||
| 668 | if counter_release(&PRIO_HIGH_ISR_COUNTER) { | ||
| 669 | nvic_enable(mac::RADIO_INTR_NUM); | ||
| 670 | } | ||
| 671 | } | ||
| 672 | |||
| 673 | if (isr_type & link_layer::LL_LOW_ISR_ONLY as u8) != 0 { | ||
| 674 | if counter_release(&PRIO_LOW_ISR_COUNTER) { | ||
| 675 | nvic_enable(RADIO_SW_LOW_INTR_NUM); | ||
| 676 | } | ||
| 677 | } | ||
| 678 | |||
| 679 | if (isr_type & link_layer::SYS_LOW_ISR as u8) != 0 { | ||
| 680 | if counter_release(&PRIO_SYS_ISR_COUNTER) { | ||
| 681 | let stored = LOCAL_BASEPRI_VALUE.load(Ordering::Relaxed) as u8; | ||
| 682 | basepri::write(stored); | ||
| 683 | } | ||
| 684 | } | ||
| 685 | } | ||
| 686 | |||
| 687 | // /** | ||
| 688 | // * @brief Disable specific interrupt group. | ||
| 689 | // * @param isr_type: mask for interrupt group to disable. | ||
| 690 | // * This parameter can be one of the following: | ||
| 691 | // * @arg LL_HIGH_ISR_ONLY: disable link layer high priority ISR. | ||
| 692 | // * @arg LL_LOW_ISR_ONLY: disable link layer SW low priority ISR. | ||
| 693 | // * @arg SYS_LOW_ISR: unmask interrupts for all the other system ISR with | ||
| 694 | // * lower priority that link layer SW low interrupt. | ||
| 695 | // * @retval None | ||
| 696 | // */ | ||
| 697 | #[unsafe(no_mangle)] | ||
| 698 | pub unsafe extern "C" fn LINKLAYER_PLAT_DisableSpecificIRQ(isr_type: u8) { | ||
| 699 | // if( (isr_type & LL_HIGH_ISR_ONLY) != 0 ) | ||
| 700 | // { | ||
| 701 | // prio_high_isr_counter++; | ||
| 702 | // if(prio_high_isr_counter == 1) | ||
| 703 | // { | ||
| 704 | // /* USER CODE BEGIN LINKLAYER_PLAT_DisableSpecificIRQ_1 */ | ||
| 705 | // | ||
| 706 | // /* USER CODE END LINKLAYER_PLAT_DisableSpecificIRQ_1 */ | ||
| 707 | // /* When specific counter for link layer high ISR value is 1, interrupt is disabled */ | ||
| 708 | // HAL_NVIC_DisableIRQ(RADIO_INTR_NUM); | ||
| 709 | // } | ||
| 710 | // } | ||
| 711 | // | ||
| 712 | // if( (isr_type & LL_LOW_ISR_ONLY) != 0 ) | ||
| 713 | // { | ||
| 714 | // prio_low_isr_counter++; | ||
| 715 | // if(prio_low_isr_counter == 1) | ||
| 716 | // { | ||
| 717 | // /* When specific counter for link layer SW low ISR value is 1, interrupt is disabled */ | ||
| 718 | // HAL_NVIC_DisableIRQ(RADIO_SW_LOW_INTR_NUM); | ||
| 719 | // } | ||
| 720 | // } | ||
| 721 | // | ||
| 722 | // if( (isr_type & SYS_LOW_ISR) != 0 ) | ||
| 723 | // { | ||
| 724 | // prio_sys_isr_counter++; | ||
| 725 | // if(prio_sys_isr_counter == 1) | ||
| 726 | // { | ||
| 727 | // /* Save basepri register value */ | ||
| 728 | // local_basepri_value = __get_BASEPRI(); | ||
| 729 | // | ||
| 730 | // /* Mask all other interrupts with lower priority that link layer SW low ISR */ | ||
| 731 | // __set_BASEPRI_MAX(RADIO_INTR_PRIO_LOW<<4); | ||
| 732 | // } | ||
| 733 | // } | ||
| 734 | trace!("LINKLAYER_PLAT_DisableSpecificIRQ: isr_type={}", isr_type); | ||
| 735 | if (isr_type & link_layer::LL_HIGH_ISR_ONLY as u8) != 0 { | ||
| 736 | if counter_acquire(&PRIO_HIGH_ISR_COUNTER) { | ||
| 737 | nvic_disable(mac::RADIO_INTR_NUM); | ||
| 738 | } | ||
| 739 | } | ||
| 740 | |||
| 741 | if (isr_type & link_layer::LL_LOW_ISR_ONLY as u8) != 0 { | ||
| 742 | if counter_acquire(&PRIO_LOW_ISR_COUNTER) { | ||
| 743 | nvic_disable(RADIO_SW_LOW_INTR_NUM); | ||
| 744 | } | ||
| 745 | } | ||
| 746 | |||
| 747 | if (isr_type & link_layer::SYS_LOW_ISR as u8) != 0 { | ||
| 748 | if counter_acquire(&PRIO_SYS_ISR_COUNTER) { | ||
| 749 | let current = basepri::read(); | ||
| 750 | LOCAL_BASEPRI_VALUE.store(current.into(), Ordering::Relaxed); | ||
| 751 | set_basepri_max(pack_priority(mac::RADIO_INTR_PRIO_LOW)); | ||
| 752 | } | ||
| 753 | } | ||
| 754 | } | ||
| 755 | |||
| 756 | // /** | ||
| 757 | // * @brief Enable link layer high priority ISR only. | ||
| 758 | // * @param None | ||
| 759 | // * @retval None | ||
| 760 | // */ | ||
| 761 | #[unsafe(no_mangle)] | ||
| 762 | pub unsafe extern "C" fn LINKLAYER_PLAT_EnableRadioIT() { | ||
| 763 | trace!("LINKLAYER_PLAT_EnableRadioIT"); | ||
| 764 | nvic_enable(mac::RADIO_INTR_NUM); | ||
| 765 | } | ||
| 766 | |||
| 767 | // /** | ||
| 768 | // * @brief Disable link layer high priority ISR only. | ||
| 769 | // * @param None | ||
| 770 | // * @retval None | ||
| 771 | // */ | ||
| 772 | #[unsafe(no_mangle)] | ||
| 773 | pub unsafe extern "C" fn LINKLAYER_PLAT_DisableRadioIT() { | ||
| 774 | trace!("LINKLAYER_PLAT_DisableRadioIT"); | ||
| 775 | nvic_disable(mac::RADIO_INTR_NUM); | ||
| 776 | } | ||
| 777 | |||
| 778 | // /** | ||
| 779 | // * @brief Link Layer notification for radio activity start. | ||
| 780 | // * @param None | ||
| 781 | // * @retval None | ||
| 782 | // */ | ||
| 783 | #[unsafe(no_mangle)] | ||
| 784 | pub unsafe extern "C" fn LINKLAYER_PLAT_StartRadioEvt() { | ||
| 785 | trace!("LINKLAYER_PLAT_StartRadioEvt"); | ||
| 786 | // __HAL_RCC_RADIO_CLK_SLEEP_ENABLE(); | ||
| 787 | // NVIC_SetPriority(RADIO_INTR_NUM, RADIO_INTR_PRIO_HIGH); | ||
| 788 | // #if (CFG_SCM_SUPPORTED == 1) | ||
| 789 | // scm_notifyradiostate(SCM_RADIO_ACTIVE); | ||
| 790 | // #endif /* CFG_SCM_SUPPORTED */ | ||
| 791 | nvic_set_priority(mac::RADIO_INTR_NUM, pack_priority(mac::RADIO_INTR_PRIO_HIGH)); | ||
| 792 | nvic_enable(mac::RADIO_INTR_NUM); | ||
| 793 | } | ||
| 794 | |||
| 795 | // /** | ||
| 796 | // * @brief Link Layer notification for radio activity end. | ||
| 797 | // * @param None | ||
| 798 | // * @retval None | ||
| 799 | // */ | ||
| 800 | #[unsafe(no_mangle)] | ||
| 801 | pub unsafe extern "C" fn LINKLAYER_PLAT_StopRadioEvt() { | ||
| 802 | trace!("LINKLAYER_PLAT_StopRadioEvt"); | ||
| 803 | // { | ||
| 804 | // __HAL_RCC_RADIO_CLK_SLEEP_DISABLE(); | ||
| 805 | // NVIC_SetPriority(RADIO_INTR_NUM, RADIO_INTR_PRIO_LOW); | ||
| 806 | // #if (CFG_SCM_SUPPORTED == 1) | ||
| 807 | // scm_notifyradiostate(SCM_RADIO_NOT_ACTIVE); | ||
| 808 | // #endif /* CFG_SCM_SUPPORTED */ | ||
| 809 | nvic_set_priority(mac::RADIO_INTR_NUM, pack_priority(mac::RADIO_INTR_PRIO_LOW)); | ||
| 810 | } | ||
| 811 | |||
| 812 | // /** | ||
| 813 | // * @brief Link Layer notification for RCO calibration start. | ||
| 814 | // * @param None | ||
| 815 | // * @retval None | ||
| 816 | // */ | ||
| 817 | #[unsafe(no_mangle)] | ||
| 818 | pub unsafe extern "C" fn LINKLAYER_PLAT_RCOStartClbr() { | ||
| 819 | trace!("LINKLAYER_PLAT_RCOStartClbr"); | ||
| 820 | // #if (CFG_LPM_LEVEL != 0) | ||
| 821 | // PWR_DisableSleepMode(); | ||
| 822 | // /* Disabling stop mode prevents also from entering in standby */ | ||
| 823 | // UTIL_LPM_SetStopMode(1U << CFG_LPM_LL_HW_RCO_CLBR, UTIL_LPM_DISABLE); | ||
| 824 | // #endif /* (CFG_LPM_LEVEL != 0) */ | ||
| 825 | // #if (CFG_SCM_SUPPORTED == 1) | ||
| 826 | // scm_setsystemclock(SCM_USER_LL_HW_RCO_CLBR, HSE_32MHZ); | ||
| 827 | // while (LL_PWR_IsActiveFlag_VOS() == 0); | ||
| 828 | // #endif /* (CFG_SCM_SUPPORTED == 1) */ | ||
| 829 | } | ||
| 830 | |||
| 831 | // /** | ||
| 832 | // * @brief Link Layer notification for RCO calibration end. | ||
| 833 | // * @param None | ||
| 834 | // * @retval None | ||
| 835 | // */ | ||
| 836 | #[unsafe(no_mangle)] | ||
| 837 | pub unsafe extern "C" fn LINKLAYER_PLAT_RCOStopClbr() { | ||
| 838 | trace!("LINKLAYER_PLAT_RCOStopClbr"); | ||
| 839 | // #if (CFG_LPM_LEVEL != 0) | ||
| 840 | // PWR_EnableSleepMode(); | ||
| 841 | // UTIL_LPM_SetStopMode(1U << CFG_LPM_LL_HW_RCO_CLBR, UTIL_LPM_ENABLE); | ||
| 842 | // #endif /* (CFG_LPM_LEVEL != 0) */ | ||
| 843 | // #if (CFG_SCM_SUPPORTED == 1) | ||
| 844 | // scm_setsystemclock(SCM_USER_LL_HW_RCO_CLBR, HSE_16MHZ); | ||
| 845 | // #endif /* (CFG_SCM_SUPPORTED == 1) */ | ||
| 846 | } | ||
| 847 | |||
| 848 | // /** | ||
| 849 | // * @brief Link Layer requests temperature. | ||
| 850 | // * @param None | ||
| 851 | // * @retval None | ||
| 852 | // */ | ||
| 853 | #[unsafe(no_mangle)] | ||
| 854 | pub unsafe extern "C" fn LINKLAYER_PLAT_RequestTemperature() { | ||
| 855 | trace!("LINKLAYER_PLAT_RequestTemperature"); | ||
| 856 | // #if (USE_TEMPERATURE_BASED_RADIO_CALIBRATION == 1) | ||
| 857 | // ll_sys_bg_temperature_measurement(); | ||
| 858 | // #endif /* USE_TEMPERATURE_BASED_RADIO_CALIBRATION */ | ||
| 859 | } | ||
| 860 | |||
| 861 | // /** | ||
| 862 | // * @brief PHY Start calibration. | ||
| 863 | // * @param None | ||
| 864 | // * @retval None | ||
| 865 | // */ | ||
| 866 | #[unsafe(no_mangle)] | ||
| 867 | pub unsafe extern "C" fn LINKLAYER_PLAT_PhyStartClbr() { | ||
| 868 | trace!("LINKLAYER_PLAT_PhyStartClbr"); | ||
| 869 | } | ||
| 870 | |||
| 871 | // /** | ||
| 872 | // * @brief PHY Stop calibration. | ||
| 873 | // * @param None | ||
| 874 | // * @retval None | ||
| 875 | // */ | ||
| 876 | #[unsafe(no_mangle)] | ||
| 877 | pub unsafe extern "C" fn LINKLAYER_PLAT_PhyStopClbr() { | ||
| 878 | trace!("LINKLAYER_PLAT_PhyStopClbr"); | ||
| 879 | } | ||
| 880 | |||
| 881 | // /** | ||
| 882 | // * @brief Notify the upper layer that new Link Layer timings have been applied. | ||
| 883 | // * @param evnt_timing[in]: Evnt_timing_t pointer to structure contains drift time , execution time and scheduling time | ||
| 884 | // * @retval None. | ||
| 885 | // */ | ||
| 886 | #[unsafe(no_mangle)] | ||
| 887 | pub unsafe extern "C" fn LINKLAYER_PLAT_SCHLDR_TIMING_UPDATE_NOT(_timings: *const link_layer::Evnt_timing_t) { | ||
| 888 | trace!("LINKLAYER_PLAT_SCHLDR_TIMING_UPDATE_NOT: timings={:?}", _timings); | ||
| 889 | } | ||
| 890 | |||
| 891 | // /** | ||
| 892 | // * @brief Get the ST company ID. | ||
| 893 | // * @param None | ||
| 894 | // * @retval Company ID | ||
| 895 | // */ | ||
| 896 | #[unsafe(no_mangle)] | ||
| 897 | pub unsafe extern "C" fn LINKLAYER_PLAT_GetSTCompanyID() -> u32 { | ||
| 898 | // STMicroelectronics Bluetooth SIG Company Identifier | ||
| 899 | // TODO: Pull in update from latest stm32-generated-data | ||
| 900 | 0x0030 | ||
| 901 | } | ||
| 902 | |||
| 903 | // /** | ||
| 904 | // * @brief Get the Unique Device Number (UDN). | ||
| 905 | // * @param None | ||
| 906 | // * @retval UDN | ||
| 907 | // */ | ||
| 908 | #[unsafe(no_mangle)] | ||
| 909 | pub unsafe extern "C" fn LINKLAYER_PLAT_GetUDN() -> u32 { | ||
| 910 | // Read the first 32 bits of the STM32 unique 96-bit ID | ||
| 911 | let uid = embassy_stm32::uid::uid(); | ||
| 912 | u32::from_le_bytes([uid[0], uid[1], uid[2], uid[3]]) | ||
| 913 | } | ||
