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#define  LFCLK_FREQUENCY_HZ  DT_PROP(LFCLK_NODE, clock_frequency)
5857
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
62+ 
5963#if  defined(CONFIG_TEST )
6064const  int32_t  z_sys_timer_irq_for_test  =  DT_IRQN (GRTC_NODE );
6165#endif 
6266
6367static  void  sys_clock_timeout_handler (int32_t  id , uint64_t  cc_val , void  * p_context );
6468
65- static  struct  k_spinlock  lock ;
6669static  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. */ 
6773static  atomic_t  int_mask ;
6874static  uint8_t  ext_channels_allocated ;
6975static  uint64_t  grtc_start_value ;
@@ -146,17 +152,13 @@ static void compare_int_unlock(int32_t chan, bool key)
146152static  void  sys_clock_timeout_handler (int32_t  id , uint64_t  cc_val , void  * p_context )
147153{
148154	ARG_UNUSED (id );
155+ 	ARG_UNUSED (cc_val );
149156	ARG_UNUSED (p_context );
150- 	uint64_t  dticks ;
151- 	uint64_t  now  =  counter ();
152- 
153- 	if  (unlikely (now  <  cc_val )) {
154- 		return ;
155- 	}
157+ 	uint32_t  dticks ;
156158
157159	dticks  =  counter_sub (cc_val , last_count ) / CYC_PER_TICK ;
158- 
159- 	last_count   +=   dticks   *   CYC_PER_TICK ;
160+ 	 last_count   +=  ( dticks   *   CYC_PER_TICK ); 
161+ 	expired_cc   =   cc_val ;
160162
161163	if  (!IS_ENABLED (CONFIG_TICKLESS_KERNEL )) {
162164		/* protection is not needed because we are in the GRTC interrupt 
@@ -165,6 +167,7 @@ static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_conte
165167		system_timeout_set_abs (last_count  +  CYC_PER_TICK );
166168	}
167169
170+ 	last_elapsed  =  0 ;
168171	sys_clock_announce ((int32_t )dticks );
169172}
170173
@@ -368,6 +371,7 @@ uint64_t z_nrf_grtc_timer_startup_value_get(void)
368371int  z_nrf_grtc_wakeup_prepare (uint64_t  wake_time_us )
369372{
370373	nrfx_err_t  err_code ;
374+ 	static  struct  k_spinlock  lock ;
371375	static  uint8_t  systemoff_channel ;
372376	uint64_t  now  =  counter ();
373377	nrfx_grtc_sleep_config_t  sleep_cfg ;
@@ -430,20 +434,12 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us)
430434
431435uint32_t  sys_clock_cycle_get_32 (void )
432436{
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 ;
437+ 	return  nrf_grtc_sys_counter_low_get (NRF_GRTC );
438438}
439439
440440uint64_t  sys_clock_cycle_get_64 (void )
441441{
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 ;
442+ 	return  counter ();
447443}
448444
449445uint32_t  sys_clock_elapsed (void )
@@ -452,7 +448,9 @@ uint32_t sys_clock_elapsed(void)
452448		return  0 ;
453449	}
454450
455- 	return  (uint32_t )(counter_sub (counter (), last_count ) / CYC_PER_TICK );
451+ 	last_elapsed  =  (uint32_t )counter_sub (counter (), last_count );
452+ 
453+ 	return  last_elapsed  / CYC_PER_TICK ;
456454}
457455
458456static  int  sys_clock_driver_init (void )
@@ -493,6 +491,10 @@ static int sys_clock_driver_init(void)
493491
494492	last_count  =  (counter () / CYC_PER_TICK ) *  CYC_PER_TICK ;
495493	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+ 
496498	int_mask  =  NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK ;
497499	if  (!IS_ENABLED (CONFIG_TICKLESS_KERNEL )) {
498500		system_timeout_set_relative (CYC_PER_TICK );
@@ -551,18 +553,48 @@ void sys_clock_set_timeout(int32_t ticks, bool idle)
551553		return ;
552554	}
553555
554- 	ticks  =  (ticks  ==  K_TICKS_FOREVER ) ? MAX_TICKS  : MIN (MAX_TICKS , MAX (ticks , 0 ));
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+ 		}
555569
556- 	uint64_t  delta_time  =  ticks  *  CYC_PER_TICK ;
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+ 	}
557577
558- 	uint64_t  target_time  =  counter () +  delta_time ;
578+ 	uint64_t  cyc  =  (uint64_t )ticks  *  CYC_PER_TICK ;
579+ 	bool  safe_setting  =  false;
580+ 	int64_t  prev_cc_val  =  cc_value ;
559581
560- 	/* Rounded down target_time to the tick boundary 
561- 	 * (but not less than one tick after the last) 
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. 
562590	 */ 
563- 	target_time  =  MAX ((target_time  -  last_count )/CYC_PER_TICK , 1 )* CYC_PER_TICK  +  last_count ;
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+ 	}
564596
565- 	system_timeout_set_abs ( target_time );
597+ 	nrfx_grtc_syscounter_cc_abs_set ( ch ,  cc_value ,  safe_setting );
566598}
567599
568600#if  defined(CONFIG_NRF_GRTC_TIMER_APP_DEFINED_INIT )
0 commit comments