Skip to content

Commit 50aa11e

Browse files
committed
drivers: timer: native_sim_timer: keep the model ticking at the tick period
hwtimer_enable() sets the period the timer model free-runs at, so arming the next announce with it stretched that period out to the whole span and let the model reach the deadline in a single step. The model paces simulated time against real time once per tick expiry, so one step of the whole span leaves nothing to pace it. Under CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME an idle with no timeout arms 0x7fffffff ticks, simulated time leaves the wall clock ~248 days behind in one go, and the model then tries to sleep off the difference. Simulated time is no longer related to real time and anything sharing the simulation with a real-world peer stalls: CI hit this on the native offloaded sockets tests that talk to a host TLS server (net.sockets.tls12.ec_kex, net.sockets.tls12.psk_kex and sample.net.sockets.http_get.nsos.https all hung in connect()). Arm through hwtimer_set_silent_ticks() instead, as the driver did before the conversion: the period stays at one tick, the model keeps stepping -- and pacing -- a tick at a time, and the ticks up to the deadline are passed over without raising an interrupt. hwtimer_enable() goes back to the single call at init that sets that period. Fixes: 0342c93 ("drivers: timer: native_sim_timer: use the generic timer core") Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org> Assisted-by: Claude:opus-5
1 parent 7fe0fd9 commit 50aa11e

1 file changed

Lines changed: 22 additions & 4 deletions

File tree

drivers/timer/native_sim_timer.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <zephyr/init.h>
1414
#include <zephyr/drivers/timer/system_timer.h>
1515
#include <zephyr/sys/clock.h>
16+
#include <zephyr/sys/util.h>
1617
#include "nsi_hw_scheduler.h"
1718
#include "nsi_timer_model.h"
1819
#include "soc.h"
@@ -26,13 +27,27 @@ static uint64_t timer_driver_cycle_get(void)
2627
return nsi_hws_get_time();
2728
}
2829

30+
/* Microseconds per kernel tick, the core's TIMER_CORE_CYC_PER_TICK, needed here
31+
* before the core is included.
32+
*/
33+
#define NP_TICK_PERIOD_US (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
34+
2935
/**
30-
* Program the next tick interrupt <cycles> microseconds from now.
31-
* hwtimer_enable() re-anchors the tick period at the current time.
36+
* Program the next tick interrupt <cycles> microseconds from now, by passing over
37+
* the tick expiries in between.
38+
*
39+
* Stretching the model's tick period with hwtimer_enable() instead would let it
40+
* reach the deadline in a single step, which leaves CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME
41+
* with nothing to pace simulated time against: that runs once per tick expiry.
42+
*
43+
* Skipping lands on the model's tick grid, so this can fire up to a tick early.
44+
* The core announces what actually elapsed and the kernel re-arms.
3245
*/
3346
static void timer_driver_set_reload(uint64_t cycles)
3447
{
35-
hwtimer_enable(cycles);
48+
int64_t silent_ticks = (int64_t)(cycles / NP_TICK_PERIOD_US) - 1;
49+
50+
hwtimer_set_silent_ticks(MAX(silent_ticks, 0));
3651
}
3752

3853
/*
@@ -44,6 +59,9 @@ static void timer_driver_set_reload(uint64_t cycles)
4459

4560
#include "system_timer_generic.h"
4661

62+
BUILD_ASSERT(NP_TICK_PERIOD_US == TIMER_CORE_CYC_PER_TICK,
63+
"the tick period used to arm the model must match the core's");
64+
4765
/**
4866
* Interrupt handler for the timer interrupt
4967
* Announce to the kernel that a number of ticks have passed
@@ -81,7 +99,7 @@ void sys_clock_disable(void)
8199
*/
82100
static int sys_clock_driver_init(void)
83101
{
84-
hwtimer_enable(TIMER_CORE_CYC_PER_TICK);
102+
hwtimer_enable(NP_TICK_PERIOD_US);
85103

86104
IRQ_CONNECT(TIMER_TICK_IRQ, 1, np_timer_isr, 0, 0);
87105
irq_enable(TIMER_TICK_IRQ);

0 commit comments

Comments
 (0)