embassy-rs/embassy · error

Radio sleep timer clock not configured (RADIOSTSEL=DISABLE)

Error message

Radio sleep timer clock not configured (RADIOSTSEL=DISABLE)

What it means

Before entering low-power sleep, the WBA link layer needs a sleep-timer clock source read from RCC BDCR field RADIOSTSEL. embassy-stm32-wpan maps each valid selection (LSE/LSI/HSE) to the link-layer constant; if RCC reports RADIOSTSEL=DISABLE, there is no sleep clock and ll_sys_sleep_clock_source_selection panics.

Solutions

  1. Configure RCC's radio sleep timer clock source (set RADIOSTSEL to LSE, LSI, or HSE) in your RCC init before starting the link layer
  2. Verify the backup domain / LSE oscillator is enabled so BDCR keeps the RADIOSTSEL setting
  3. Check the STM32WBA example RCC init in embassy examples and replicate the radio clock setup

Example fix

// before (no radio clock configured)
let mut config = Config::default();
// RCC default: RADIOSTSEL = Disable
// after
config.rcc.radio_sleep_clock = Some(RadioSleepClock {
    source: RadioSleepClockSource::Lse,
    // frequency as required for LSE
});
Defensive patterns

Strategy: validation

Validate before calling

// before starting the link layer, assert the RCC sleep clock is set:
let rcc = unsafe { peris::RCC::steal() };
assert!(rcc.bdcr().read().radiostsel() != Radiostsel::Disable, "set radio sleep clock in RCC init");

Prevention

When it happens

Trigger: Calling ll_sys_config_params or ll_sys_reset (which invoke ll_sys_sleep_clock_source_selection) when RCC.bdcr().radiostsel() reads Disable — i.e. the radio sleep timer clock was never configured in RCC setup.

Common situations: Skipping/omitting the RCC configuration snippet for the radio sleep clock when bringing up STM32WBA; resetting BDCR (e.g. after backup-domain reset) leaving RADIOSTSEL at its default; copying init code from a different chip family that lacks the RADIOSTSEL setup.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/de56eab278125c4c. Report an issue: GitHub.

Appendix: source

Thrown at embassy-stm32-wpan/src/wba/ll_sys_if.rs:410

    let sleep_accuracy = ll_sys_BLE_sleep_clock_accuracy_selection();
    let _ = link_layer::ll_intf_le_set_sleep_clock_accuracy(sleep_accuracy);
}

/// Select the sleep-clock source used by the Link Layer.
/// Reads the RCC BDCR register to determine which clock source has been
/// configured for the radio sleep timer and tells the link-layer accordingly.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ll_sys_sleep_clock_source_selection() {
    use embassy_stm32::pac::RCC;
    use embassy_stm32::pac::rcc::vals::Radiostsel;

    let radiostsel = RCC.bdcr().read().radiostsel();
    let slp_clk_src = match radiostsel {
        Radiostsel::Lse => link_layer::_slptmr_src_type_e_RTC_SLPTMR as u8,
        Radiostsel::Lsi => link_layer::_slptmr_src_type_e_RCO_SLPTMR as u8,
        Radiostsel::Hse => link_layer::_slptmr_src_type_e_CRYSTAL_OSCILLATOR_SLPTMR as u8,
        Radiostsel::Disable => panic!("Radio sleep timer clock not configured (RADIOSTSEL=DISABLE)"),
    };

    let mut frequency: u16 = 0;
    let _ = link_layer::ll_intf_cmn_le_select_slp_clk_src(slp_clk_src, &mut frequency as *mut u16);
}

/// Determine the BLE sleep-clock accuracy used by the stack.
///
/// Values follow the BLE Sleep Clock Accuracy range encoding used by the
/// link-layer/HCI (0 = 251-500 ppm ... 7 = 0-20 ppm).
#[unsafe(no_mangle)]
pub unsafe extern "C" fn ll_sys_BLE_sleep_clock_accuracy_selection() -> u8 {
    use embassy_stm32::pac::RCC;
    use embassy_stm32::pac::rcc::vals::Radiostsel;

    // BLE SCA range encoding (Bluetooth Core, Vol 6, Part B).
    const BLE_SCA_251_TO_500_PPM: u8 = 0;
    const BLE_SCA_021_TO_030_PPM: u8 = 6;

View on GitHub (pinned to 463a07b963)