From cf23839a2e83383820e2172f12154de975b5c43f Mon Sep 17 00:00:00 2001 From: Emanuele Di Santo Date: Wed, 15 Apr 2026 18:48:40 +0200 Subject: [PATCH] softdevice: add babblesim support Add SoftDevice babblesim support. Signed-off-by: Emanuele Di Santo --- samples/Kconfig | 2 +- subsys/softdevice/CMakeLists.txt | 5 ++ subsys/softdevice/Kconfig | 14 +++-- subsys/softdevice_handler/CMakeLists.txt | 16 +++--- subsys/softdevice_handler/Kconfig | 3 +- subsys/softdevice_handler/irq_connect.c | 4 +- subsys/softdevice_handler/irq_connect_bsim.c | 57 ++++++++++++++++++++ subsys/softdevice_handler/nrf_sdh.c | 8 +-- subsys/softdevice_handler/nrf_sdh_ble.c | 7 +++ subsys/softdevice_handler/rand_seed.c | 11 ++-- west.yml | 1 - 11 files changed, 102 insertions(+), 26 deletions(-) create mode 100644 subsys/softdevice_handler/irq_connect_bsim.c diff --git a/samples/Kconfig b/samples/Kconfig index be1ad3d521..45fe60dd05 100644 --- a/samples/Kconfig +++ b/samples/Kconfig @@ -8,7 +8,7 @@ # All these samples shall run without multithreading config MULTITHREADING - default n if (!UNITY && !(ZTEST && BOARD_NATIVE_SIM)) + default n if (!UNITY && !(ZTEST && BOARD_NATIVE_SIM) && !SOC_SERIES_BSIM_NRF54LX) # Software ISR table is not needed if multithreading is not used config GEN_SW_ISR_TABLE diff --git a/subsys/softdevice/CMakeLists.txt b/subsys/softdevice/CMakeLists.txt index 7924ba647a..72c01a7c2b 100644 --- a/subsys/softdevice/CMakeLists.txt +++ b/subsys/softdevice/CMakeLists.txt @@ -7,3 +7,8 @@ if(CONFIG_SOFTDEVICE_S115 OR CONFIG_SOFTDEVICE_S145) zephyr_include_directories("${ZEPHYR_NRF_BM_MODULE_DIR}/components/softdevice/${CONFIG_SOFTDEVICE_SOC_VARIANT_STR}/${CONFIG_SOFTDEVICE_VARIANT_STR}/${CONFIG_SOFTDEVICE_VARIANT_STR}_API/include") endif() + +# SVCALL_AS_NORMAL_FUNCTION makes BLE API headers declare normal functions (no ARM SVC asm). +if(CONFIG_SOFTDEVICE_BSIM) + zephyr_compile_definitions(SVCALL_AS_NORMAL_FUNCTION) +endif() diff --git a/subsys/softdevice/Kconfig b/subsys/softdevice/Kconfig index 678e743377..5b57f95dcd 100644 --- a/subsys/softdevice/Kconfig +++ b/subsys/softdevice/Kconfig @@ -7,7 +7,7 @@ menu "SoftDevice" config SOFTDEVICE bool "SoftDevice is present" - depends on ZERO_LATENCY_IRQS + depends on ZERO_LATENCY_IRQS || SOC_SERIES_BSIM_NRF54LX imply NRF_SDH config SOFTDEVICE_PERIPHERAL @@ -32,13 +32,13 @@ choice SOFTDEVICE_VARIANT config SOFTDEVICE_S115 bool "s115 SoftDevice" - depends on SOC_SERIES_NRF54L + depends on SOC_SERIES_NRF54L || SOC_SERIES_BSIM_NRF54LX select SOFTDEVICE_PERIPHERAL select SOFTDEVICE_DATA_LENGTH_UPDATE config SOFTDEVICE_S145 bool "s145 SoftDevice" - depends on SOC_SERIES_NRF54L + depends on SOC_SERIES_NRF54L || SOC_SERIES_BSIM_NRF54LX select SOFTDEVICE_PERIPHERAL select SOFTDEVICE_CENTRAL select SOFTDEVICE_EXTENDED_ADVERTISING @@ -46,6 +46,12 @@ config SOFTDEVICE_S145 endchoice # SOFTDEVICE_VARIANT +config SOFTDEVICE_BSIM + bool "Use linkable SoftDevice for Babblesim" + depends on SOC_SERIES_BSIM_NRF54LX + help + Link with the SoftDevice library instead of using the separate SoftDevice hex image. + config SOFTDEVICE_VARIANT_STR string default "s115" if SOFTDEVICE_S115 @@ -56,7 +62,7 @@ config SOFTDEVICE_VARIANT_STR config SOFTDEVICE_SOC_VARIANT_STR string - default "nrf54l" if SOC_NRF54L15 || SOC_NRF54L10 || SOC_NRF54L05 + default "nrf54l" if SOC_NRF54L15 || SOC_NRF54L10 || SOC_NRF54L05 || SOC_SERIES_BSIM_NRF54LX default "nrf54lm" if SOC_NRF54LM20A default "nrf54ls" if SOC_NRF54LS05B default "nrf54lv" if SOC_NRF54LV10A diff --git a/subsys/softdevice_handler/CMakeLists.txt b/subsys/softdevice_handler/CMakeLists.txt index 4338a13838..8d7a8db7dc 100644 --- a/subsys/softdevice_handler/CMakeLists.txt +++ b/subsys/softdevice_handler/CMakeLists.txt @@ -6,18 +6,24 @@ zephyr_library() zephyr_linker_sources(SECTIONS sdh.ld) zephyr_linker_sources(DATA_SECTIONS sdh_ram.ld) + zephyr_library_sources( nrf_sdh.c nrf_sdh_info.c nrf_sdh_soc.c - irq_connect.c ) +zephyr_library_sources_ifdef(CONFIG_NRF_SDH_BLE nrf_sdh_ble.c) zephyr_library_sources_ifdef(CONFIG_NRF_SDH_SOC_RAND_SEED rand_seed.c) -if(CONFIG_SOFTDEVICE_S115 OR CONFIG_SOFTDEVICE_S145) - zephyr_library_sources(irq_forward.s) +# IRQ setup +if(CONFIG_SOFTDEVICE_BSIM) + zephyr_library_sources(irq_connect_bsim.c) +else() + # ARM-only: IRQ connection, SVC forwarding and swap_helper suppression # Suppress the swap_helper.S file so that z_arm_svc can be defined manually + zephyr_library_sources(irq_connect.c) + zephyr_library_sources(irq_forward.s) set(cortex_m_dir ${ZEPHYR_BASE}/arch/arm/core/cortex_m) set_property( SOURCE ${cortex_m_dir}/swap_helper.S @@ -26,7 +32,3 @@ if(CONFIG_SOFTDEVICE_S115 OR CONFIG_SOFTDEVICE_S145) ) target_link_options(app PUBLIC "-Wl,--defsym=z_arm_svc=SVC_Handler") endif() - -if(CONFIG_NRF_SDH_BLE) - zephyr_library_sources(nrf_sdh_ble.c) -endif() diff --git a/subsys/softdevice_handler/Kconfig b/subsys/softdevice_handler/Kconfig index 4c6d654b33..b86e9715ad 100644 --- a/subsys/softdevice_handler/Kconfig +++ b/subsys/softdevice_handler/Kconfig @@ -237,8 +237,7 @@ endif # NRF_SDH_BLE config NRF_SDH_SOC_RAND_SEED bool "Automatically seed SoftDevice random" - depends on NRF_SECURITY - depends on MBEDTLS_PSA_CRYPTO_C + depends on (NRF_SECURITY && MBEDTLS_PSA_CRYPTO_C) || SOC_SERIES_BSIM_NRF54LX default y help Automatically seed SoftDevice using CRACEN to generate the random seed. diff --git a/subsys/softdevice_handler/irq_connect.c b/subsys/softdevice_handler/irq_connect.c index 7b1ad13d49..1c0befb698 100644 --- a/subsys/softdevice_handler/irq_connect.c +++ b/subsys/softdevice_handler/irq_connect.c @@ -14,9 +14,9 @@ LOG_MODULE_DECLARE(nrf_sdh, CONFIG_NRF_SDH_LOG_LEVEL); -#if CONFIG_SOC_SERIES_NRF54L #include "irq_connect.h" +/* Handlers provided by the SoftDevice */ extern void CLOCK_POWER_SD_IRQHandler(void); extern void RADIO_0_IRQHandler(void); extern void TIMER10_IRQHandler(void); @@ -121,6 +121,4 @@ __attribute__((weak)) void C_CLOCK_POWER_SD_Handler(void) #endif } -#endif /* CONFIG_SOC_SERIES_NRF54L */ - SYS_INIT(irq_init, APPLICATION, 0); diff --git a/subsys/softdevice_handler/irq_connect_bsim.c b/subsys/softdevice_handler/irq_connect_bsim.c new file mode 100644 index 0000000000..780024a8e2 --- /dev/null +++ b/subsys/softdevice_handler/irq_connect_bsim.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + * + * Register all SoftDevice IRQ handlers with the native simulator. + * SD_EVT_IRQn (SWI01) is connected in nrf_sdh.c (sd_irq_init), same as on ARM. + */ + +#include +#include +#include + +/* Handlers provided by the linked SoftDevice library */ +extern void C_RTC0_Handler(void); +extern void C_SIGNALLING_Handler(void); +extern void C_RADIO_Handler(void); +extern void C_POWER_CLOCK_Handler(void); +extern void C_TIMER0_Handler(void); +extern void C_ECB_Handler(void); +extern void C_CCM_Handler(void); + +#define SD_IRQ_PRIO_HIGH 0 +#define SD_IRQ_PRIO_LOW 4 + +#define IRQ_WRAPPER(name, handler) \ + static void name##_wrapper(const void *arg) { ARG_UNUSED(arg); handler(); } + +IRQ_WRAPPER(grtc3, C_RTC0_Handler); +IRQ_WRAPPER(swi00, C_SIGNALLING_Handler); +IRQ_WRAPPER(radio0, C_RADIO_Handler); + +IRQ_WRAPPER(clock_power, C_POWER_CLOCK_Handler); +IRQ_WRAPPER(timer10, C_TIMER0_Handler); +IRQ_WRAPPER(ecb00, C_ECB_Handler); +IRQ_WRAPPER(aar00_ccm00, C_CCM_Handler); + +#define REGISTER(irqn, irqp, wrapper) do { \ + (void)irq_connect_dynamic(irqn, irqp, wrapper##_wrapper, NULL, 0); \ + irq_enable(irqn); \ +} while (0) + +static int softdevice_bsim_irq_init(void) +{ + REGISTER(GRTC_3_IRQn, SD_IRQ_PRIO_HIGH, grtc3); + REGISTER(TIMER10_IRQn, SD_IRQ_PRIO_HIGH, timer10); + REGISTER(RADIO_0_IRQn, SD_IRQ_PRIO_HIGH, radio0); + + REGISTER(SWI00_IRQn, SD_IRQ_PRIO_LOW, swi00); + REGISTER(CLOCK_POWER_IRQn, SD_IRQ_PRIO_LOW, clock_power); + REGISTER(ECB00_IRQn, SD_IRQ_PRIO_LOW, ecb00); + REGISTER(AAR00_CCM00_IRQn, SD_IRQ_PRIO_LOW, aar00_ccm00); + + return 0; +} + +SYS_INIT(softdevice_bsim_irq_init, APPLICATION, 0); diff --git a/subsys/softdevice_handler/nrf_sdh.c b/subsys/softdevice_handler/nrf_sdh.c index fb997273ea..5de72900e1 100644 --- a/subsys/softdevice_handler/nrf_sdh.c +++ b/subsys/softdevice_handler/nrf_sdh.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -131,7 +132,8 @@ static int nrf_sdh_enable(void) .hfint_ctiv = CONFIG_NRF_SDH_CLOCK_HFINT_CALIBRATION_INTERVAL, }; - if (IS_ENABLED(CONFIG_NRF_SDH_LOG_SD_INFO)) { +#if defined(CONFIG_NRF_SDH_LOG_SD_INFO) && !defined(CONFIG_SOFTDEVICE_BSIM) + { const uint32_t base = FIXED_PARTITION_OFFSET(softdevice_partition); const struct nrf_sdh_info_version sd_ver = nrf_sdh_info_version_get(base); const struct nrf_sdh_info_unique_str sd_unique = nrf_sdh_info_unique_str_get(base); @@ -149,6 +151,7 @@ static int nrf_sdh_enable(void) sd_ver.bugfix); } } +#endif err = sd_softdevice_enable(&clock_lf_cfg, softdevice_fault_handler); if (err) { @@ -392,8 +395,7 @@ ISR_DIRECT_DECLARE(sd_direct_isr) static int sd_irq_init(void) { - BM_IRQ_DIRECT_CONNECT(SD_EVT_IRQn, SD_EVT_IRQ_PRI, - sd_direct_isr, 0); + BM_IRQ_DIRECT_CONNECT(SD_EVT_IRQn, SD_EVT_IRQ_PRI, sd_direct_isr, 0); irq_enable(SD_EVT_IRQn); return 0; diff --git a/subsys/softdevice_handler/nrf_sdh_ble.c b/subsys/softdevice_handler/nrf_sdh_ble.c index d4aa3c08e4..0d9656d783 100644 --- a/subsys/softdevice_handler/nrf_sdh_ble.c +++ b/subsys/softdevice_handler/nrf_sdh_ble.c @@ -12,8 +12,15 @@ #include #include +#if defined(CONFIG_SOFTDEVICE_BSIM) +extern uint32_t g_app_ram_base; +extern uint32_t bsim_softdevice_ram_end; +#define APP_RAM_START (bsim_softdevice_ram_end) +#define SD_RAM_START (g_app_ram_base) +#else #define APP_RAM_START DT_REG_ADDR(DT_CHOSEN(zephyr_sram)) #define SD_RAM_START DT_REG_ADDR(DT_NODELABEL(cpuapp_sram)) +#endif LOG_MODULE_DECLARE(nrf_sdh, CONFIG_NRF_SDH_LOG_LEVEL); diff --git a/subsys/softdevice_handler/rand_seed.c b/subsys/softdevice_handler/rand_seed.c index 2054a175e9..aec4bcb6b3 100644 --- a/subsys/softdevice_handler/rand_seed.c +++ b/subsys/softdevice_handler/rand_seed.c @@ -7,17 +7,16 @@ #include #include #include -#include #if CONFIG_HAS_HW_NRF_CRACEN +#include #include -#else +#elif CONFIG_NRFX_CRACEN #include #endif LOG_MODULE_DECLARE(nrf_sdh, CONFIG_NRF_SDH_LOG_LEVEL); -/* Extern in nrf_sdh.c */ -void sdh_soc_rand_seed(uint32_t evt, void *ctx) +static void sdh_soc_rand_seed(uint32_t evt, void *ctx) { uint32_t nrf_err; uint8_t seed[SD_RAND_SEED_SIZE]; @@ -37,7 +36,7 @@ void sdh_soc_rand_seed(uint32_t evt, void *ctx) LOG_ERR("Failed to generate true random number, psa_status %d", status); return; } -#else +#elif CONFIG_NRFX_CRACEN && !CONFIG_SOFTDEVICE_BSIM /* Selected when we don't have CRACEN Crypto HW available, like for nRF54LS05B * In this case the cracen_psa api isn't available and we should use nrfx api */ @@ -47,6 +46,8 @@ void sdh_soc_rand_seed(uint32_t evt, void *ctx) LOG_ERR("Failed to generate true random number, err %d", err); return; } +#elif CONFIG_SOFTDEVICE_BSIM + /* Seed with heap garbage */ #endif nrf_err = sd_rand_seed_set(seed); diff --git a/west.yml b/west.yml index 9b32ccc2f4..ff5009af2c 100644 --- a/west.yml +++ b/west.yml @@ -19,7 +19,6 @@ manifest: name-allowlist: - cmsis - cmsis_6 - - dragoon - hal_nordic - lz4 - mbedtls