4949#define COUNTER_SPAN (GRTC_SYSCOUNTERL_VALUE_Msk | ((uint64_t)GRTC_SYSCOUNTERH_VALUE_Msk << 32))
5050#define MAX_ABS_TICKS (COUNTER_SPAN / CYC_PER_TICK)
5151
52- #define MAX_TICKS \
53- (((COUNTER_SPAN / CYC_PER_TICK) > INT_MAX) ? INT_MAX : (COUNTER_SPAN / CYC_PER_TICK))
54-
55- #define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK)
52+ /* To allow use of CCADD we need to limit max cycles to 31 bits. */
53+ #define MAX_REL_CYCLES BIT_MASK(31)
54+ #define MAX_REL_TICKS (MAX_REL_CYCLES / CYC_PER_TICK)
5655
5756#if DT_NODE_HAS_STATUS_OKAY (LFCLK_NODE )
5857#define LFCLK_FREQUENCY_HZ DT_PROP(LFCLK_NODE, clock_frequency)
5958#else
6059#define LFCLK_FREQUENCY_HZ CONFIG_CLOCK_CONTROL_NRF_K32SRC_FREQUENCY
6160#endif
6261
62+ /* Threshold used to determine if there is a risk of unexpected GRTC COMPARE event coming
63+ * from previous CC value.
64+ */
65+ #define LATENCY_THR_TICKS 200
66+
6367#if defined(CONFIG_TEST )
6468const int32_t z_sys_timer_irq_for_test = DT_IRQN (GRTC_NODE );
6569#endif
6670
6771static void sys_clock_timeout_handler (int32_t id , uint64_t cc_val , void * p_context );
6872
69- static struct k_spinlock lock ;
7073static uint64_t last_count ; /* Time (SYSCOUNTER value) @last sys_clock_announce() */
74+ static uint64_t last_elapsed ;
75+ static uint64_t cc_value ; /* Value that is expected to be in CC register. */
76+ static uint64_t expired_cc ; /* Value that is expected to be in CC register. */
7177static atomic_t int_mask ;
7278static uint8_t ext_channels_allocated ;
7379static uint64_t grtc_start_value ;
@@ -151,16 +157,11 @@ static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_conte
151157{
152158ARG_UNUSED (id );
153159ARG_UNUSED (p_context );
154- uint64_t dticks ;
155- uint64_t now = counter ();
156-
157- if (unlikely (now < cc_val )) {
158- return ;
159- }
160+ uint32_t dticks ;
160161
161162dticks = counter_sub (cc_val , last_count ) / CYC_PER_TICK ;
162-
163- last_count += dticks * CYC_PER_TICK ;
163+ last_count += ( dticks * CYC_PER_TICK );
164+ expired_cc = cc_val ;
164165
165166if (!IS_ENABLED (CONFIG_TICKLESS_KERNEL )) {
166167/* protection is not needed because we are in the GRTC interrupt
@@ -169,6 +170,7 @@ static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_conte
169170system_timeout_set_abs (last_count + CYC_PER_TICK );
170171}
171172
173+ last_elapsed = 0 ;
172174sys_clock_announce ((int32_t )dticks );
173175}
174176
@@ -367,6 +369,7 @@ uint64_t z_nrf_grtc_timer_startup_value_get(void)
367369int z_nrf_grtc_wakeup_prepare (uint64_t wake_time_us )
368370{
369371nrfx_err_t err_code ;
372+ static struct k_spinlock lock ;
370373static uint8_t systemoff_channel ;
371374uint64_t now = counter ();
372375nrfx_grtc_sleep_config_t sleep_cfg ;
@@ -429,20 +432,12 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
429432
430433uint32_t sys_clock_cycle_get_32 (void )
431434{
432- k_spinlock_key_t key = k_spin_lock (& lock );
433- uint32_t ret = (uint32_t )counter ();
434-
435- k_spin_unlock (& lock , key );
436- return ret ;
435+ return (uint32_t )counter ();
437436}
438437
439438uint64_t sys_clock_cycle_get_64 (void )
440439{
441- k_spinlock_key_t key = k_spin_lock (& lock );
442- uint64_t ret = counter ();
443-
444- k_spin_unlock (& lock , key );
445- return ret ;
440+ return counter ();
446441}
447442
448443uint32_t sys_clock_elapsed (void )
@@ -451,7 +446,9 @@ uint32_t sys_clock_elapsed(void)
451446return 0 ;
452447}
453448
454- return (uint32_t )(counter_sub (counter (), last_count ) / CYC_PER_TICK );
449+ last_elapsed = counter_sub (counter (), last_count );
450+
451+ return (uint32_t )(last_elapsed / CYC_PER_TICK );
455452}
456453
457454#if !defined(CONFIG_GEN_SW_ISR_TABLE )
@@ -507,6 +504,10 @@ static int sys_clock_driver_init(void)
507504
508505last_count = (counter () / CYC_PER_TICK ) * CYC_PER_TICK ;
509506grtc_start_value = last_count ;
507+ expired_cc = UINT64_MAX ;
508+ nrfx_grtc_channel_callback_set (system_clock_channel_data .channel ,
509+ sys_clock_timeout_handler , NULL );
510+
510511int_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK ;
511512if (!IS_ENABLED (CONFIG_TICKLESS_KERNEL )) {
512513system_timeout_set_relative (CYC_PER_TICK );
@@ -570,18 +571,47 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
570571return ;
571572}
572573
573- ticks = ( ticks == K_TICKS_FOREVER ) ? MAX_TICKS : MIN ( MAX_TICKS , MAX ( ticks , 0 )) ;
574+ uint32_t ch = system_clock_channel_data . channel ;
574575
575- uint64_t delta_time = ticks * CYC_PER_TICK ;
576+ if ((cc_value == expired_cc ) && (ticks <= MAX_REL_TICKS )) {
577+ uint32_t cyc = ticks * CYC_PER_TICK ;
576578
577- uint64_t target_time = counter () + delta_time ;
579+ if (cyc == 0 ) {
580+ /* GRTC will expire anyway since HW ensures that past value triggers an
581+ * event but we need to ensure to always progress the cc_value as this
582+ * if condition expects that cc_value will change after each call to
583+ * set_timeout function.
584+ */
585+ cyc = 1 ;
586+ }
578587
579- /* Rounded down target_time to the tick boundary
580- * (but not less than one tick after the last)
588+ /* If it's the first timeout setting after previous expiration and timeout
589+ * is short so fast method can be used which utilizes relative CC configuration.
590+ */
591+ cc_value += cyc ;
592+ nrfx_grtc_syscounter_cc_rel_set (ch , cyc , NRFX_GRTC_CC_RELATIVE_COMPARE );
593+ return ;
594+ }
595+
596+ uint64_t cyc = (uint64_t )ticks * CYC_PER_TICK ;
597+ bool safe_setting = false;
598+ uint64_t prev_cc_val = cc_value ;
599+ uint64_t now = last_count + last_elapsed ;
600+
601+ cc_value = now + cyc ;
602+
603+ /* In case of timeout abort it may happen that CC is being set to a value
604+ * that later than previous CC. If previous CC value is not far in the
605+ * future, there is a risk that COMPARE event will be triggered for that
606+ * previous CC value. If there is such risk safe procedure must be applied
607+ * which is more time consuming but ensures that there will be no spurious
608+ * event.
581609 */
582- target_time = MAX ((target_time - last_count )/CYC_PER_TICK , 1 )* CYC_PER_TICK + last_count ;
610+ if (prev_cc_val < cc_value ) {
611+ safe_setting = (int64_t )(prev_cc_val - now ) < LATENCY_THR_TICKS ;
612+ }
583613
584- system_timeout_set_abs ( target_time );
614+ nrfx_grtc_syscounter_cc_abs_set ( ch , cc_value , safe_setting );
585615}
586616
587617#if defined(CONFIG_NRF_GRTC_TIMER_APP_DEFINED_INIT )
0 commit comments