This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 598a1035a054fef7ebe0ae3f5c5f743e03ccdc32 Author: Lingao Meng <[email protected]> AuthorDate: Thu Jul 23 14:44:40 2026 +0800 arch/sim: Add BabbleSim discrete time support Add support for using a BabbleSim PHY as the monotonic time source for the Linux sim target. When CONFIG_SIM_BSIM_TIME is enabled, the sim host build links a small host-side time helper against the BabbleSim PhyCom and Util libraries. The helper joins the BabbleSim PHY wait protocol and advances NuttX monotonic time through PB_MSG_WAIT requests instead of Linux wall-time sleeps. A SIM binary built with CONFIG_SIM_BSIM_TIME enabled joins BabbleSim time at startup. Runtime options allow the test runner to select the BabbleSim simulation id, PHY id, and device number: --sim-bsim-sid=<simulation-id> --sim-bsim-pid=<phy-id> --sim-bsim-dev=<device-number> Keep the integration inside the sim host time path rather than exposing a new application API. RTC/realtime reads still use the host realtime clock; the BabbleSim source is used only for monotonic time after the sim has joined the PHY. The Kconfig option depends on the sleep based walltime mode and is disabled for SMP and non-Linux hosts. The build requires BSIM_COMPONENTS_PATH for headers and either BSIM_OUT_PATH or BSIM_LIBS_DIR for shared libraries. The path checks are skipped for clean, distclean, clean_context, and context targets so a tree with CONFIG_SIM_BSIM_TIME enabled can still be cleaned without exporting the BabbleSim environment first. Document the configuration, build environment, runtime options, and the requirement that the BabbleSim PHY process is started separately by the test runner. Testing: Host: Ubuntu 22.04 x86_64 Board/config: sim:nsh Style check: git diff --check Default sim build and smoke test: ./tools/configure.sh -l -a ../nuttx-apps sim:nsh make -j16 printf 'help\npoweroff\n' | timeout 20s ./nuttx BabbleSim-enabled build: kconfig-tweak --file .config \ -e SIM_WALLTIME_SLEEP \ -d SIM_WALLTIME_SIGNAL \ -e SIM_BSIM_TIME make olddefconfig BSIM_OUT_PATH=/tmp/bsworld/build/babblesim/bsim \ BSIM_COMPONENTS_PATH=/tmp/bsworld/build/babblesim/bsim/components \ make -j16 Verified actual BabbleSim PHY time integration without a controller by starting bs_2G4_phy_v1 and running NSH usleep through the PHY wait barrier: bs_2G4_phy_v1 -s=<sid> -D=1 -defmodem=BLE_simple -nodump printf 'usleep 1000000\npoweroff\n' | \ ./nuttx --sim-bsim-sid=<sid> \ --sim-bsim-pid=2G4 \ --sim-bsim-dev=0 The same 1 second simulated sleep completed in 19 ms wall time when no handbrake device was present. With handbrake registered as device 1: bs_2G4_phy_v1 -s=<sid> -D=2 -defmodem=BLE_simple -nodump bs_device_handbrake -s=<sid> -p=2G4 -d=1 -pp=50000 -r=1 the same NuttX usleep test completed in 985 ms wall time. A shorter 200 ms check showed the same behavior: 27 ms without handbrake and 172 ms with handbrake. This verifies that NuttX sim time advances through the BabbleSim PHY and that the handbrake affects the NuttX sim device. Also verified make distclean succeeds after CONFIG_SIM_BSIM_TIME was enabled and without exporting BSIM_COMPONENTS_PATH. BSWorld out-of-tree native BLE examples: ./tools/configure.sh -l /path/to/bsim-auto-test/tests/nuttx/native_ble/source/advertiser/config make -j16 exodus --tarball -o /path/to/bsim-auto-test/tests/nuttx/native_ble/source/advertiser/prebuilt/nuttx.tgz nuttx ./tools/configure.sh -l /path/to/bsim-auto-test/tests/nuttx/native_ble/source/scanner/config make -j16 exodus --tarball -o /path/to/bsim-auto-test/tests/nuttx/native_ble/source/scanner/prebuilt/nuttx.tgz nuttx pytest tests/nuttx/native_ble -q --no-ellisys Assisted-by: OpenAI Codex Signed-off-by: Lingao Meng <[email protected]> --- .../platforms/sim/sim/boards/sim/index.rst | 37 ++++++ arch/sim/Kconfig | 42 +++++++ arch/sim/src/Makefile | 25 ++++ arch/sim/src/sim/posix/sim_bsimtime.c | 130 +++++++++++++++++++++ arch/sim/src/sim/posix/sim_hosttime.c | 23 ++++ arch/sim/src/sim/sim_head.c | 29 +++++ arch/sim/src/sim/sim_internal.h | 9 ++ 7 files changed, 295 insertions(+) diff --git a/Documentation/platforms/sim/sim/boards/sim/index.rst b/Documentation/platforms/sim/sim/boards/sim/index.rst index 59b19ba81ca..4326dac0318 100644 --- a/Documentation/platforms/sim/sim/boards/sim/index.rst +++ b/Documentation/platforms/sim/sim/boards/sim/index.rst @@ -41,6 +41,43 @@ Timing Fidelity Another option is to use ``CONFIG_SIM_WALLTIME_SLEEP`` which will enable the tick events to be delayed from the Idle task by using a host sleep call. +BabbleSim Discrete Time +----------------------- + +The Linux ``sim`` target can optionally use a BabbleSim PHY process as the +monotonic time source. This is useful for tests where a NuttX host-side stack +and other BabbleSim devices need to advance in the same discrete-time domain. + +Enable ``CONFIG_SIM_BSIM_TIME`` together with ``CONFIG_SIM_WALLTIME_SLEEP``. +This mode is available only on Linux hosts and is not supported with SMP or +``CONFIG_SIM_WALLTIME_SIGNAL``. + +When ``CONFIG_SIM_BSIM_TIME`` is enabled, the build needs the BabbleSim +component headers and libraries: + +.. code:: console + + $ export BSIM_OUT_PATH=/path/to/bsim + $ export BSIM_COMPONENTS_PATH=${BSIM_OUT_PATH}/components + +``BSIM_LIBS_DIR`` may be used instead of ``BSIM_OUT_PATH`` when the BabbleSim +shared libraries are installed in a non-default directory. + +When ``CONFIG_SIM_BSIM_TIME`` is enabled, the simulator connects to the +BabbleSim PHY at startup: + +.. code:: console + + $ ./nuttx --sim-bsim-sid=default \ + --sim-bsim-pid=2G4 \ + --sim-bsim-dev=0 + +The BabbleSim PHY process must be started separately by the test runner before +launching the NuttX simulator. + +The runtime options override ``CONFIG_SIM_BSIM_SIM_ID``, +``CONFIG_SIM_BSIM_PHY_ID``, and ``CONFIG_SIM_BSIM_DEVICE_NBR``. + Debugging ========= diff --git a/arch/sim/Kconfig b/arch/sim/Kconfig index 70b1f3c88ab..29675843803 100644 --- a/arch/sim/Kconfig +++ b/arch/sim/Kconfig @@ -180,6 +180,48 @@ config SIM_WALLTIME_RATIO twice as fast as real time. 50 means half speed. This can also be overridden at runtime with --sim-rt-ratio=<percent>. +config SIM_BSIM_TIME + bool "Enable BabbleSim PHY time support" + default n + depends on HOST_LINUX + depends on SIM_WALLTIME_SLEEP + depends on !SMP + ---help--- + Build support for using the BabbleSim PHY wait protocol as the SIM + monotonic time source. When this option is enabled, the SIM target + participates in the PHY discrete-time barrier as a device, and + host_sleepuntil() advances by sending PB_MSG_WAIT requests instead + of sleeping on Linux wall time. + + This is intended for tests where the host stack and controller need + to share the same simulated time domain. The signal-driven walltime + timer mode is intentionally not supported. + + The build must be given the BabbleSim paths through the environment: + BSIM_COMPONENTS_PATH for headers and either BSIM_OUT_PATH or + BSIM_LIBS_DIR for libraries. + +config SIM_BSIM_SIM_ID + string "BabbleSim simulation ID" + default "default" + depends on SIM_BSIM_TIME + ---help--- + The BabbleSim simulation ID passed to the PHY with -s. + +config SIM_BSIM_PHY_ID + string "BabbleSim PHY ID" + default "2G4" + depends on SIM_BSIM_TIME + ---help--- + The BabbleSim PHY ID. This must match the PHY process ID. + +config SIM_BSIM_DEVICE_NBR + int "BabbleSim device number for this SIM host" + default 0 + depends on SIM_BSIM_TIME + ---help--- + The BabbleSim device number reserved for this SIM host. + config SIM_LOOP_INTERVAL int "loop interval in ms" default 10 diff --git a/arch/sim/src/Makefile b/arch/sim/src/Makefile index fbd900d8e82..1883aee10b3 100644 --- a/arch/sim/src/Makefile +++ b/arch/sim/src/Makefile @@ -134,6 +134,31 @@ endif HOSTSRCS = sim_hostirq.c sim_hostmemory.c sim_hostmisc.c sim_hosttime.c sim_hostuart.c HOSTSRCS += sim_hostfs.c sim_errno.c +ifeq ($(CONFIG_SIM_BSIM_TIME),y) + HOSTSRCS += sim_bsimtime.c + ifeq ($(BSIM_COMPONENTS_PATH),) + $(error CONFIG_SIM_BSIM_TIME requires BSIM_COMPONENTS_PATH to point to \ + the BabbleSim components directory) + endif + ifeq ($(BSIM_LIBS_DIR),) + ifeq ($(BSIM_OUT_PATH),) + $(error CONFIG_SIM_BSIM_TIME requires BSIM_LIBS_DIR or BSIM_OUT_PATH \ + to locate BabbleSim libraries) + endif + BSIM_LIBS_DIR := $(BSIM_OUT_PATH)/lib + endif + HOSTCFLAGS += ${INCDIR_PREFIX}$(BSIM_COMPONENTS_PATH)/libPhyComv1/src + HOSTCFLAGS += ${INCDIR_PREFIX}$(BSIM_COMPONENTS_PATH)/libUtilv1/src + STDLIBS += -Wl,-rpath,$(BSIM_LIBS_DIR) + ifeq ($(CONFIG_SIM_M32),y) + STDLIBS += $(BSIM_LIBS_DIR)/libPhyComv1.32.so + STDLIBS += $(BSIM_LIBS_DIR)/libUtilv1.32.so + else + STDLIBS += $(BSIM_LIBS_DIR)/libPhyComv1.so + STDLIBS += $(BSIM_LIBS_DIR)/libUtilv1.so + endif +endif + hostfs.h: $(TOPDIR)/include/nuttx/fs/hostfs.h @echo "CP: $<" $(Q) cp $< $@ diff --git a/arch/sim/src/sim/posix/sim_bsimtime.c b/arch/sim/src/sim/posix/sim_bsimtime.c new file mode 100644 index 00000000000..2e1d019d718 --- /dev/null +++ b/arch/sim/src/sim/posix/sim_bsimtime.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * arch/sim/src/sim/posix/sim_bsimtime.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <errno.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> + +#include "bs_pc_base.h" +#include "sim_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NSEC_PER_BSIM_USEC 1000ull + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static pb_dev_state_t g_bsim_dev; +static uint64_t g_now_nsec; +static bool g_connected; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void bsimtime_disconnect_atexit(void) +{ + host_bsimtime_disconnect(); +} + +static void bsimtime_fail(void) +{ + host_abort(1); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int host_bsimtime_init(const char *sim_id, const char *phy_id, + unsigned int dev_nbr) +{ + int ret; + + if (sim_id == NULL || phy_id == NULL) + { + return -EINVAL; + } + + ret = pb_dev_init_com(&g_bsim_dev, dev_nbr, sim_id, phy_id); + if (ret != 0) + { + return ret; + } + + g_connected = true; + atexit(bsimtime_disconnect_atexit); + + return 0; +} + +uint64_t host_bsimtime_gettime(void) +{ + return g_now_nsec; +} + +bool host_bsimtime_is_enabled(void) +{ + return g_connected; +} + +void host_bsimtime_sleepuntil(uint64_t nsec) +{ + pb_wait_t wait; + + if (nsec <= g_now_nsec) + { + return; + } + + if (!g_connected) + { + bsimtime_fail(); + } + + wait.end = (nsec + NSEC_PER_BSIM_USEC - 1) / NSEC_PER_BSIM_USEC; + + if (pb_dev_request_wait_block(&g_bsim_dev, &wait) < 0) + { + bsimtime_fail(); + } + + g_now_nsec = wait.end * NSEC_PER_BSIM_USEC; +} + +void host_bsimtime_disconnect(void) +{ + if (!g_connected) + { + return; + } + + pb_dev_disconnect(&g_bsim_dev); + g_connected = false; +} diff --git a/arch/sim/src/sim/posix/sim_hosttime.c b/arch/sim/src/sim/posix/sim_hosttime.c index 0eaefa4158a..ec527ed0829 100644 --- a/arch/sim/src/sim/posix/sim_hosttime.c +++ b/arch/sim/src/sim/posix/sim_hosttime.c @@ -109,6 +109,13 @@ uint64_t host_gettime(bool rtc) struct timespec tp; uint64_t current; +#ifdef CONFIG_SIM_BSIM_TIME + if (!rtc && host_bsimtime_is_enabled()) + { + return host_bsimtime_gettime(); + } +#endif + clock_gettime(rtc ? CLOCK_REALTIME : CLOCK_MONOTONIC, &tp); current = 1000000000ull * tp.tv_sec + tp.tv_nsec; @@ -128,6 +135,14 @@ uint64_t host_gettime(bool rtc) void host_sleep(uint64_t nsec) { +#ifdef CONFIG_SIM_BSIM_TIME + if (host_bsimtime_is_enabled()) + { + host_sleepuntil(host_gettime(false) + nsec); + return; + } +#endif + usleep((nsec + 999) / 1000); } @@ -139,6 +154,14 @@ void host_sleepuntil(uint64_t nsec) { uint64_t now; +#ifdef CONFIG_SIM_BSIM_TIME + if (host_bsimtime_is_enabled()) + { + host_bsimtime_sleepuntil(nsec); + return; + } +#endif + now = host_gettime(false); if (nsec > now + 1000) { diff --git a/arch/sim/src/sim/sim_head.c b/arch/sim/src/sim/sim_head.c index dc625cd925c..1e6a2176b19 100644 --- a/arch/sim/src/sim/sim_head.c +++ b/arch/sim/src/sim/sim_head.c @@ -165,6 +165,11 @@ noprofile_function const char *__ubsan_default_options(void) int main(int argc, char **argv, char **envp) { +#ifdef CONFIG_SIM_BSIM_TIME + const char *bsim_sim_id = CONFIG_SIM_BSIM_SIM_ID; + const char *bsim_phy_id = CONFIG_SIM_BSIM_PHY_ID; + unsigned int bsim_dev_nbr = CONFIG_SIM_BSIM_DEVICE_NBR; +#endif int i; g_argc = argc; @@ -173,6 +178,9 @@ int main(int argc, char **argv, char **envp) /* Parse simulator-specific options before handing control to NuttX. * --sim-rt-ratio=<percent> Set simulated-to-real time ratio in percent * (default 100). Values > 100 speed up simulated time; < 100 slow down. + * --sim-bsim-sid=<id> Override the BabbleSim simulation ID. + * --sim-bsim-pid=<id> Override the BabbleSim PHY ID. + * --sim-bsim-dev=<n> Override the BabbleSim device number. */ for (i = 1; i < argc; i++) @@ -181,7 +189,28 @@ int main(int argc, char **argv, char **envp) { host_set_timeratio(atoi(argv[i] + 15)); } +#ifdef CONFIG_SIM_BSIM_TIME + else if (strncmp(argv[i], "--sim-bsim-sid=", 15) == 0) + { + bsim_sim_id = argv[i] + 15; + } + else if (strncmp(argv[i], "--sim-bsim-pid=", 15) == 0) + { + bsim_phy_id = argv[i] + 15; + } + else if (strncmp(argv[i], "--sim-bsim-dev=", 15) == 0) + { + bsim_dev_nbr = atoi(argv[i] + 15); + } +#endif + } + +#ifdef CONFIG_SIM_BSIM_TIME + if (host_bsimtime_init(bsim_sim_id, bsim_phy_id, bsim_dev_nbr) < 0) + { + return EXIT_FAILURE; } +#endif #ifdef CONFIG_ALLSYMS allsyms_relocate(); diff --git a/arch/sim/src/sim/sim_internal.h b/arch/sim/src/sim/sim_internal.h index 9f256838cd6..82ace1ecdd4 100644 --- a/arch/sim/src/sim/sim_internal.h +++ b/arch/sim/src/sim/sim_internal.h @@ -249,6 +249,15 @@ void host_set_timeratio(int ratio); int host_timerirq(void); int host_settimer(uint64_t nsec); +#ifdef CONFIG_SIM_BSIM_TIME +int host_bsimtime_init(const char *sim_id, const char *phy_id, + unsigned int dev_nbr); +uint64_t host_bsimtime_gettime(void); +bool host_bsimtime_is_enabled(void); +void host_bsimtime_sleepuntil(uint64_t nsec); +void host_bsimtime_disconnect(void); +#endif + /* sim_sigdeliver.c *********************************************************/ void sim_sigdeliver(void);
