From fb4af2c707ae6360185d6f2a48bac14309ee54dd Mon Sep 17 00:00:00 2001 From: Adam Kondraciuk Date: Wed, 11 Jun 2025 13:37:19 +0200 Subject: [PATCH 1/2] drivers: timer: nrf_grtc_timer: add last_count initialization The GRTC counter is not cleared at startup, therefore the `last_count` variable needs to be initialized accordingly. This change: - Prevents overflow of the `sys_clock_announce()` int32_t parameter - Ensures the correct uptime value, which should be reset during initialization Signed-off-by: Adam Kondraciuk --- drivers/timer/nrf_grtc_timer.c | 8 ++++++++ include/zephyr/drivers/timer/nrf_grtc_timer.h | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/timer/nrf_grtc_timer.c b/drivers/timer/nrf_grtc_timer.c index 285e48a57fd2f..2809d8b3d608d 100644 --- a/drivers/timer/nrf_grtc_timer.c +++ b/drivers/timer/nrf_grtc_timer.c @@ -66,6 +66,7 @@ static struct k_spinlock lock; static uint64_t last_count; /* Time (SYSCOUNTER value) @last sys_clock_announce() */ static atomic_t int_mask; static uint8_t ext_channels_allocated; +static uint64_t grtc_start_value; static nrfx_grtc_channel_t system_clock_channel_data = { .handler = sys_clock_timeout_handler, .p_context = NULL, @@ -358,6 +359,11 @@ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time) return 0; } +uint64_t z_nrf_grtc_timer_startup_value_get(void) +{ + return grtc_start_value; +} + #if defined(CONFIG_POWEROFF) && defined(CONFIG_NRF_GRTC_START_SYSCOUNTER) int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) { @@ -485,6 +491,8 @@ static int sys_clock_driver_init(void) } #endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */ + last_count = (counter() / CYC_PER_TICK) * CYC_PER_TICK; + grtc_start_value = last_count; int_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { system_timeout_set_relative(CYC_PER_TICK); diff --git a/include/zephyr/drivers/timer/nrf_grtc_timer.h b/include/zephyr/drivers/timer/nrf_grtc_timer.h index f8b69d7ddf021..5a51df217442b 100644 --- a/include/zephyr/drivers/timer/nrf_grtc_timer.h +++ b/include/zephyr/drivers/timer/nrf_grtc_timer.h @@ -189,6 +189,17 @@ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time); */ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us); +/** @brief Get the GRTC counter value latched at startup. + * + * @note The GRTC timer is not cleared by software at startup, + * while the system tick starts counting from zero. + * In some cases, it may be necessary to compare the system tick + * with the GRTC value — in such situations, this offset can be useful. + * + * @return GRTC value latched during system clock initialization. + */ +uint64_t z_nrf_grtc_timer_startup_value_get(void); + /** * @brief Initialize the GRTC clock timer driver from an application- * defined function. From 6248aac8a4a085ab27a13033ecf2ef3f69097a3d Mon Sep 17 00:00:00 2001 From: Adam Kondraciuk Date: Thu, 12 Jun 2025 12:34:01 +0200 Subject: [PATCH 2/2] tests: drivers: timer: nrf_grtc_timer: Align tests with uptime changes Update GRTC tests to reflect uptime reset at startup. Signed-off-by: Adam Kondraciuk --- tests/drivers/timer/nrf_grtc_timer/src/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/drivers/timer/nrf_grtc_timer/src/main.c b/tests/drivers/timer/nrf_grtc_timer/src/main.c index f53188841bdb0..cede54f026f13 100644 --- a/tests/drivers/timer/nrf_grtc_timer/src/main.c +++ b/tests/drivers/timer/nrf_grtc_timer/src/main.c @@ -28,6 +28,7 @@ ZTEST(nrf_grtc_timer, test_get_ticks) { k_timeout_t t = K_MSEC(1); + uint64_t grtc_start_value = z_nrf_grtc_timer_startup_value_get(); uint64_t exp_ticks = z_nrf_grtc_timer_read() + t.ticks * CYC_PER_TICK; int64_t ticks; @@ -51,6 +52,7 @@ ZTEST(nrf_grtc_timer, test_get_ticks) curr_tick2 = sys_clock_tick_get(); } while (curr_tick != curr_tick2); + curr_tick += (grtc_start_value / CYC_PER_TICK); t = Z_TIMEOUT_TICKS(Z_TICK_ABS(curr_tick - K_MSEC(1).ticks)); exp_ticks = curr_grtc_tick - K_MSEC(1).ticks * CYC_PER_TICK; @@ -69,6 +71,7 @@ ZTEST(nrf_grtc_timer, test_get_ticks) curr_tick2 = sys_clock_tick_get(); } while (curr_tick != curr_tick2); + curr_tick += (grtc_start_value / CYC_PER_TICK); t = Z_TIMEOUT_TICKS(Z_TICK_ABS(curr_tick + K_MSEC(10).ticks)); exp_ticks = curr_grtc_tick + K_MSEC(10).ticks * CYC_PER_TICK; ticks = z_nrf_grtc_timer_get_ticks(t);