diff --git a/drivers/timer/nrf_grtc_timer.c b/drivers/timer/nrf_grtc_timer.c index 285e48a57fd2..2809d8b3d608 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 f8b69d7ddf02..5a51df217442 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. diff --git a/tests/drivers/timer/nrf_grtc_timer/src/main.c b/tests/drivers/timer/nrf_grtc_timer/src/main.c index f53188841bdb..cede54f026f1 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);