Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 70 additions & 2 deletions Documentation/platforms/sim/sim/boards/sim/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
=========

Expand Down Expand Up @@ -614,18 +651,49 @@ the NULL Bluetooth device at ``drivers/wireless/bluetooth/bt_null.c``.
There is also support on a Linux Host for attaching the bluetooth hardware from
the host to the NuttX bluetooth stack via the HCI Socket interface over the User
Channel. This is enabled in the bthcisock configuration. In order to use this
you must give the ``nuttx`` ELF additional capabilities:
with the configured default HCI device, you must give the ``nuttx`` ELF
additional capabilities:

.. code:: console

$ sudo setcap 'cap_net_raw,cap_net_admin=eip' ./nuttx

You can then monitor the HCI traffic on the host with WireShark or ``btmon``:
The default HCI device is selected by ``CONFIG_SIM_HCISOCKET_DEVID``. It may be
overridden at runtime with ``--bt-dev=hciN``:

.. code:: console

$ ./nuttx --bt-dev=hci1

You can then monitor the BlueZ HCI traffic on the host with WireShark or
``btmon``:

.. code:: console

$ sudo btmon

The sim target can also connect to an HCI H:4 stream exposed through a Unix
domain socket by passing an absolute socket path:

.. code:: console

$ ./nuttx --bt-dev=/tmp/hci0.sock

This Unix socket mode does not require a BlueZ HCI device. Since ``nuttx`` only
connects to a normal Unix domain socket, the ``nuttx`` process does not need to
run as root and does not need the ``setcap`` command above. This is useful when
the controller is provided by another host process, or when a UART controller is
bridged into a Unix socket with a tool such as ``socat``:

.. code:: console

$ socat UNIX-LISTEN:/tmp/hci0.sock,fork,reuseaddr \
/dev/ttyACM0,b1000000,raw,echo=0,crtscts=1

The process listening on the socket must be started before NuttX. If that
process opens a real UART device, it still needs permission to access that UART
device.

configdata
----------

Expand Down
47 changes: 46 additions & 1 deletion arch/sim/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -630,14 +672,17 @@ config SIM_HCISOCKET
target via HCI_CHANNEL_USER. This gives NuttX full
control of the device, but is abstracted from the
physical interface which is still handled by Linux.
The default BlueZ device can be overridden at runtime
with --bt-dev=hciN, or replaced by a Unix-domain HCI
socket with --bt-dev=/path/to/socket.

config SIM_HCISOCKET_DEVID
int "Bluetooth Device ID"
default 0
depends on SIM_HCISOCKET
---help---
Attached the local bluetooth device use specific
Bluetooth HCI number id.
Bluetooth HCI number id when --bt-dev is not passed.

config SIM_I2CBUS
bool "Simulated I2C Bus"
Expand Down
25 changes: 25 additions & 0 deletions arch/sim/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 $< $@
Expand Down
130 changes: 130 additions & 0 deletions arch/sim/src/sim/posix/sim_bsimtime.c
Original file line number Diff line number Diff line change
@@ -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;
}
Loading
Loading