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- /* 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)
52+ #define MAX_TICKS \
53+ (((COUNTER_SPAN / CYC_PER_TICK) > INT_MAX) ? INT_MAX : (COUNTER_SPAN / CYC_PER_TICK))
5554
56- #define LFCLK_FREQUENCY_HZ DT_PROP(LFCLK_NODE, clock_frequency )
55+ #define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK )
5756
58- /* Threshold used to determine if there is a risk of unexpected GRTC COMPARE event coming
59- * from previous CC value.
60- */
61- #define LATENCY_THR_TICKS 200
57+ #define LFCLK_FREQUENCY_HZ DT_PROP(LFCLK_NODE, clock_frequency)
6258
6359#if defined(CONFIG_TEST )
6460const int32_t z_sys_timer_irq_for_test = DT_IRQN (GRTC_NODE );
6561#endif
6662
6763static void sys_clock_timeout_handler (int32_t id , uint64_t cc_val , void * p_context );
6864
65+ static struct k_spinlock lock ;
6966static uint64_t last_count ; /* Time (SYSCOUNTER value) @last sys_clock_announce() */
70- static uint32_t last_elapsed ;
71- static uint64_t cc_value ; /* Value that is expected to be in CC register. */
72- static uint64_t expired_cc ; /* Value that is expected to be in CC register. */
7367static atomic_t int_mask ;
7468static uint8_t ext_channels_allocated ;
7569static uint64_t grtc_start_value ;
@@ -152,13 +146,17 @@ static void compare_int_unlock(int32_t chan, bool key)
152146static void sys_clock_timeout_handler (int32_t id , uint64_t cc_val , void * p_context )
153147{
154148 ARG_UNUSED (id );
155- ARG_UNUSED (cc_val );
156149 ARG_UNUSED (p_context );
157- uint32_t dticks ;
150+ uint64_t dticks ;
151+ uint64_t now = counter ();
152+
153+ if (unlikely (now < cc_val )) {
154+ return ;
155+ }
158156
159157 dticks = counter_sub (cc_val , last_count ) / CYC_PER_TICK ;
160- last_count += ( dticks * CYC_PER_TICK );
161- expired_cc = cc_val ;
158+
159+ last_count += dticks * CYC_PER_TICK ;
162160
163161 if (!IS_ENABLED (CONFIG_TICKLESS_KERNEL )) {
164162 /* protection is not needed because we are in the GRTC interrupt
@@ -167,7 +165,6 @@ static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_conte
167165 system_timeout_set_abs (last_count + CYC_PER_TICK );
168166 }
169167
170- last_elapsed = 0 ;
171168 sys_clock_announce ((int32_t )dticks );
172169}
173170
@@ -371,7 +368,6 @@ uint64_t z_nrf_grtc_timer_startup_value_get(void)
371368int z_nrf_grtc_wakeup_prepare (uint64_t wake_time_us )
372369{
373370 nrfx_err_t err_code ;
374- static struct k_spinlock lock ;
375371 static uint8_t systemoff_channel ;
376372 uint64_t now = counter ();
377373 nrfx_grtc_sleep_config_t sleep_cfg ;
@@ -434,12 +430,20 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
434430
435431uint32_t sys_clock_cycle_get_32 (void )
436432{
437- return nrf_grtc_sys_counter_low_get (NRF_GRTC );
433+ k_spinlock_key_t key = k_spin_lock (& lock );
434+ uint32_t ret = (uint32_t )counter ();
435+
436+ k_spin_unlock (& lock , key );
437+ return ret ;
438438}
439439
440440uint64_t sys_clock_cycle_get_64 (void )
441441{
442- return counter ();
442+ k_spinlock_key_t key = k_spin_lock (& lock );
443+ uint64_t ret = counter ();
444+
445+ k_spin_unlock (& lock , key );
446+ return ret ;
443447}
444448
445449uint32_t sys_clock_elapsed (void )
@@ -448,9 +452,7 @@ uint32_t sys_clock_elapsed(void)
448452 return 0 ;
449453 }
450454
451- last_elapsed = (uint32_t )counter_sub (counter (), last_count );
452-
453- return last_elapsed / CYC_PER_TICK ;
455+ return (uint32_t )(counter_sub (counter (), last_count ) / CYC_PER_TICK );
454456}
455457
456458static int sys_clock_driver_init (void )
@@ -491,10 +493,6 @@ static int sys_clock_driver_init(void)
491493
492494 last_count = (counter () / CYC_PER_TICK ) * CYC_PER_TICK ;
493495 grtc_start_value = last_count ;
494- expired_cc = UINT64_MAX ;
495- nrfx_grtc_channel_callback_set (system_clock_channel_data .channel ,
496- sys_clock_timeout_handler , NULL );
497-
498496 int_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK ;
499497 if (!IS_ENABLED (CONFIG_TICKLESS_KERNEL )) {
500498 system_timeout_set_relative (CYC_PER_TICK );
@@ -553,48 +551,18 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
553551 return ;
554552 }
555553
556- uint32_t ch = system_clock_channel_data .channel ;
557-
558- if ((cc_value == expired_cc ) && (ticks < MAX_REL_TICKS )) {
559- uint32_t cyc = ticks * CYC_PER_TICK ;
560-
561- if (cyc == 0 ) {
562- /* GRTC will expire anyway since HW ensures that past value triggers an
563- * event but we need to ensure to always progress the cc_value as this
564- * if condition expects that cc_value will change after each call to
565- * set_timeout function.
566- */
567- cyc = 1 ;
568- }
554+ ticks = (ticks == K_TICKS_FOREVER ) ? MAX_TICKS : MIN (MAX_TICKS , MAX (ticks , 0 ));
569555
570- /* If it's the first timeout setting after previous expiration and timeout
571- * is short so fast method can be used which utilizes relative CC configuration.
572- */
573- cc_value += cyc ;
574- nrfx_grtc_syscounter_cc_rel_set (ch , cyc , NRFX_GRTC_CC_RELATIVE_COMPARE );
575- return ;
576- }
556+ uint64_t delta_time = ticks * CYC_PER_TICK ;
577557
578- uint64_t cyc = (uint64_t )ticks * CYC_PER_TICK ;
579- bool safe_setting = false;
580- int64_t prev_cc_val = cc_value ;
558+ uint64_t target_time = counter () + delta_time ;
581559
582- cc_value = last_count + last_elapsed + cyc ;
583-
584- /* In case of timeout abort it may happen that CC is being set to a value
585- * that later than previous CC. If previous CC value is not far in the
586- * future, there is a risk that COMPARE event will be triggered for that
587- * previous CC value. If there is such risk safe procedure must be applied
588- * which is more time consuming but ensures that there will be no spurious
589- * event.
560+ /* Rounded down target_time to the tick boundary
561+ * (but not less than one tick after the last)
590562 */
591- if (prev_cc_val < cc_value ) {
592- int64_t now = last_count + last_elapsed ;
593-
594- safe_setting = (prev_cc_val - now ) < LATENCY_THR_TICKS ;
595- }
563+ target_time = MAX ((target_time - last_count )/CYC_PER_TICK , 1 )* CYC_PER_TICK + last_count ;
596564
597- nrfx_grtc_syscounter_cc_abs_set ( ch , cc_value , safe_setting );
565+ system_timeout_set_abs ( target_time );
598566}
599567
600568#if defined(CONFIG_NRF_GRTC_TIMER_APP_DEFINED_INIT )
0 commit comments