arch/sim: Add host timer to oneshot timer logic
## Summary of Changes Add a host timer that generates periodic signals and sends SIGALRM to the process that runs the NuttX simulation. This logic is integrated as part of the existing NuttX oneshot timer. The host timer installs an irq handler which is expected to run every CONFIG_USEC_PER_TICK . Signed-off-by: Sebastian Ene <nuttx@fitbit.com>
This commit is contained in:
parent
090d822f33
commit
c47ad0c909
|
@ -98,8 +98,16 @@ config SIM_X8664_MICROSOFT
|
|||
endchoice
|
||||
|
||||
config SIM_WALLTIME
|
||||
bool "Execution simulation in near real-time"
|
||||
bool "Run the simulation at a fixed cadence in near real-time"
|
||||
default n
|
||||
|
||||
if SIM_WALLTIME
|
||||
choice
|
||||
prompt "Simulation at a fixed cadence in near real-time"
|
||||
default SIM_WALLTIME_SLEEP
|
||||
|
||||
config SIM_WALLTIME_SLEEP
|
||||
bool "Execution the simulation in near real-time using host sleep"
|
||||
---help---
|
||||
NOTE: In order to facility fast testing, the sim target's IDLE loop, by default,
|
||||
calls the system timer "interrupt handler" as fast as possible. As a result, there
|
||||
|
@ -111,6 +119,18 @@ config SIM_WALLTIME
|
|||
correct for the system timer tick rate. With this definition in the configuration,
|
||||
sleep() behavior is more or less normal.
|
||||
|
||||
config SIM_WALLTIME_SIGNAL
|
||||
bool "Execute the simulation using a host timer"
|
||||
---help---
|
||||
Run the NuttX simulation using a host timer that delivers periodic SIGALRM
|
||||
events at a tick rate specified by CONFIG_USEC_PER_TICK. Enabling this option
|
||||
will generate the timer 'tick' events from the host timer at a fixed rate.
|
||||
The simulated 'tick' events from Idle task are no longer sent.
|
||||
|
||||
endchoice
|
||||
|
||||
endif
|
||||
|
||||
config SIM_NETDEV
|
||||
bool "Simulated Network Device"
|
||||
default y
|
||||
|
|
|
@ -83,6 +83,7 @@ ifeq ($(CONFIG_HOST_MACOS),y)
|
|||
HOSTCFLAGS += -Wno-deprecated-declarations
|
||||
endif
|
||||
|
||||
HOSTCFLAGS += -DCONFIG_USEC_PER_TICK=$(CONFIG_USEC_PER_TICK)
|
||||
HOSTSRCS = up_hostirq.c up_hostmemory.c up_hosttime.c up_simuart.c
|
||||
STDLIBS += -lpthread
|
||||
ifneq ($(CONFIG_HOST_MACOS),y)
|
||||
|
@ -101,7 +102,6 @@ ifeq ($(CONFIG_SMP),y)
|
|||
CSRCS += up_smpsignal.c up_cpuidlestack.c
|
||||
REQUIREDOBJS += up_smpsignal$(OBJEXT)
|
||||
HOSTCFLAGS += -DCONFIG_SMP=1 -DCONFIG_SMP_NCPUS=$(CONFIG_SMP_NCPUS)
|
||||
HOSTCFLAGS += -DCONFIG_USEC_PER_TICK=$(CONFIG_USEC_PER_TICK)
|
||||
ifeq ($(CONFIG_SIM_WALLTIME),y)
|
||||
HOSTCFLAGS += -DCONFIG_SIM_WALLTIME=1
|
||||
endif
|
||||
|
|
|
@ -37,8 +37,11 @@
|
|||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -89,3 +92,37 @@ void host_sleepuntil(uint64_t nsec)
|
|||
usleep((nsec - now) / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: host_settimer
|
||||
*
|
||||
* Description:
|
||||
* Set up a timer to send periodic signals.
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - a pointer where we save the host signal number for SIGALRM
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, (0) zero value is returned, otherwise a negative value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int host_settimer(int *irq)
|
||||
{
|
||||
struct itimerval it;
|
||||
|
||||
if (irq == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*irq = SIGALRM;
|
||||
|
||||
it.it_interval.tv_sec = 0;
|
||||
it.it_interval.tv_usec = CONFIG_USEC_PER_TICK;
|
||||
it.it_value = it.it_interval;
|
||||
|
||||
/* Start a host timer at a rate indicated by CONFIG_USEC_PER_TICK */
|
||||
|
||||
return setitimer(ITIMER_REAL, &it, NULL);
|
||||
}
|
||||
|
|
|
@ -228,6 +228,7 @@ void host_free_shmem(void *mem);
|
|||
uint64_t host_gettime(bool rtc);
|
||||
void host_sleep(uint64_t nsec);
|
||||
void host_sleepuntil(uint64_t nsec);
|
||||
int host_settimer(int *irq);
|
||||
|
||||
/* up_simsmp.c **************************************************************/
|
||||
|
||||
|
|
|
@ -58,7 +58,8 @@
|
|||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure describes the state of the oneshot timer lower-half driver */
|
||||
/* This structure describes the state of the oneshot timer lower-half driver.
|
||||
*/
|
||||
|
||||
struct sim_oneshot_lowerhalf_s
|
||||
{
|
||||
|
@ -116,6 +117,33 @@ static const struct oneshot_operations_s g_oneshot_ops =
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sim_timer_update
|
||||
*
|
||||
* Description:
|
||||
* Ths function is called periodically to deliver the tick events to the
|
||||
* NuttX simulation.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void sim_timer_update(void)
|
||||
{
|
||||
static const struct timespec tick =
|
||||
{
|
||||
.tv_sec = 0,
|
||||
.tv_nsec = NSEC_PER_TICK,
|
||||
};
|
||||
|
||||
FAR sq_entry_t *entry;
|
||||
|
||||
clock_timespec_add(&g_current, &tick, &g_current);
|
||||
|
||||
for (entry = sq_peek(&g_oneshot_list); entry; entry = sq_next(entry))
|
||||
{
|
||||
sim_process_tick(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sim_process_tick
|
||||
*
|
||||
|
@ -299,6 +327,28 @@ static int sim_current(FAR struct oneshot_lowerhalf_s *lower,
|
|||
return OK;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SIM_WALLTIME_SIGNAL
|
||||
/****************************************************************************
|
||||
* Name: sim_alarm_handler
|
||||
*
|
||||
* Description:
|
||||
* The signal handler is called periodically and is used to deliver TICK
|
||||
* events to the OS.
|
||||
*
|
||||
* Input Parameters:
|
||||
* sig - the signal number
|
||||
* si - the signal information
|
||||
* old_ucontext - the previous context
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int sim_alarm_handler(int irq, FAR void *context, FAR void *arg)
|
||||
{
|
||||
sim_timer_update();
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_SIM_WALLTIME_SIGNAL */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -357,6 +407,17 @@ FAR struct oneshot_lowerhalf_s *oneshot_initialize(int chan,
|
|||
|
||||
void up_timer_initialize(void)
|
||||
{
|
||||
#ifdef CONFIG_SIM_WALLTIME_SIGNAL
|
||||
int host_alarm_irq;
|
||||
|
||||
host_settimer(&host_alarm_irq);
|
||||
|
||||
/* Enable the alarm handler and attach the interrupt to the NuttX logic */
|
||||
|
||||
up_enable_irq(host_alarm_irq);
|
||||
irq_attach(host_alarm_irq, sim_alarm_handler, NULL);
|
||||
#endif
|
||||
|
||||
up_alarm_set_lowerhalf(oneshot_initialize(0, 0));
|
||||
}
|
||||
|
||||
|
@ -376,25 +437,15 @@ void up_timer_initialize(void)
|
|||
|
||||
void up_timer_update(void)
|
||||
{
|
||||
static const struct timespec tick =
|
||||
{
|
||||
.tv_sec = 0,
|
||||
.tv_nsec = NSEC_PER_TICK,
|
||||
};
|
||||
#ifdef CONFIG_SIM_WALLTIME_SLEEP
|
||||
|
||||
FAR sq_entry_t *entry;
|
||||
|
||||
clock_timespec_add(&g_current, &tick, &g_current);
|
||||
|
||||
#ifdef CONFIG_SIM_WALLTIME
|
||||
/* Wait a bit so that the timing is close to the correct rate. */
|
||||
|
||||
host_sleepuntil(g_current.tv_nsec +
|
||||
(uint64_t)g_current.tv_sec * NSEC_PER_SEC);
|
||||
#endif
|
||||
|
||||
for (entry = sq_peek(&g_oneshot_list); entry; entry = sq_next(entry))
|
||||
{
|
||||
sim_process_tick(entry);
|
||||
}
|
||||
#ifndef CONFIG_SIM_WALLTIME_SIGNAL
|
||||
sim_timer_update();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -57,8 +57,12 @@ behavior that is closer to normal timing, then you can define
|
|||
CONFIG_SIM_WALLTIME=y in your configuration file. This configuration setting
|
||||
will cause the sim target's IDLE loop to delay on each call so that the system
|
||||
"timer interrupt" is called at a rate approximately correct for the system
|
||||
timer tick rate. With this definition in the configuration, sleep() behavior
|
||||
is more or less normal.
|
||||
timer tick rate. This option can be enabled with CONFIG_SIM_WALLTIME_SIGNAL
|
||||
which will drive the entire simulation by using a host timer that ticks at
|
||||
CONFIG_USEC_PER_TICK. This option will no longer deliver 'tick' events
|
||||
from Idle task and it will generate them from the host signal handler.
|
||||
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.
|
||||
|
||||
Debugging
|
||||
^^^^^^^^^
|
||||
|
|
Loading…
Reference in New Issue