diff --git a/arch/sim/Kconfig b/arch/sim/Kconfig index a165b45c3a1..a2f8bbf4acd 100644 --- a/arch/sim/Kconfig +++ b/arch/sim/Kconfig @@ -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 diff --git a/arch/sim/src/Makefile b/arch/sim/src/Makefile index 96736d4ae46..b731b52a8ae 100644 --- a/arch/sim/src/Makefile +++ b/arch/sim/src/Makefile @@ -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 diff --git a/arch/sim/src/sim/up_hosttime.c b/arch/sim/src/sim/up_hosttime.c index e0d7c4dc071..54c81a5d61a 100644 --- a/arch/sim/src/sim/up_hosttime.c +++ b/arch/sim/src/sim/up_hosttime.c @@ -37,8 +37,11 @@ * Included Files ****************************************************************************/ +#include +#include #include #include +#include #include #include @@ -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); +} diff --git a/arch/sim/src/sim/up_internal.h b/arch/sim/src/sim/up_internal.h index 983b4ef9af6..2741c64f6cd 100644 --- a/arch/sim/src/sim/up_internal.h +++ b/arch/sim/src/sim/up_internal.h @@ -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 **************************************************************/ diff --git a/arch/sim/src/sim/up_oneshot.c b/arch/sim/src/sim/up_oneshot.c index 714591136bc..ec0c6311bed 100644 --- a/arch/sim/src/sim/up_oneshot.c +++ b/arch/sim/src/sim/up_oneshot.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 } diff --git a/boards/sim/sim/sim/README.txt b/boards/sim/sim/sim/README.txt index 284b86e6184..0b6489cbb5e 100644 --- a/boards/sim/sim/sim/README.txt +++ b/boards/sim/sim/sim/README.txt @@ -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 ^^^^^^^^^