@@ -102,6 +102,9 @@ typedef struct
102
102
nrfx_atomic_t available_channels ; /**< Bitmask of available channels. */
103
103
uint32_t used_channels ; /**< Bitmask of channels used by the driver. */
104
104
nrfx_grtc_channel_t channel_data [NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS + 1 ]; /**< Channel specific data. */
105
+ uint8_t ch_to_data [GRTC_NCC_SIZE ]; /**< Mapping of channel indext to channel_data index. */
106
+ uint64_t cc_value [NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS ]; /**< Last CC value. */
107
+ nrfx_atomic_t read_cc_mask ; /**< Indicating if CC value must be passed to the handler. */
105
108
#if NRF_GRTC_HAS_RTCOUNTER
106
109
nrfx_grtc_rtcomparesync_handler_t rtcomparesync_handler ; /**< User handler corresponding to rtcomparesync event.*/
107
110
void * rtcomparesync_context ; /**< User context for rtcomparesync event handler. */
@@ -306,6 +309,18 @@ nrfx_err_t nrfx_grtc_syscounter_get(uint64_t * p_counter)
306
309
return err_code ;
307
310
}
308
311
312
+ void nrfx_grtc_channel_callback_set (uint8_t channel ,
313
+ nrfx_grtc_cc_handler_t handler ,
314
+ void * p_context )
315
+ {
316
+ uint8_t ch_data_idx = get_ch_data_index_for_channel (channel );
317
+
318
+ m_cb .channel_data [ch_data_idx ].handler = handler ;
319
+ m_cb .channel_data [ch_data_idx ].p_context = p_context ;
320
+ m_cb .channel_data [ch_data_idx ].channel = channel ;
321
+ nrfy_grtc_int_enable (NRF_GRTC , GRTC_CHANNEL_TO_BITMASK (channel ));
322
+ }
323
+
309
324
nrfx_err_t nrfx_grtc_channel_alloc (uint8_t * p_channel )
310
325
{
311
326
NRFX_ASSERT (p_channel );
@@ -394,7 +409,10 @@ nrfx_err_t nrfx_grtc_init(uint8_t interrupt_priority)
394
409
395
410
for (uint8_t i = 0 ; i < NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS ; i ++ )
396
411
{
397
- m_cb .channel_data [i ].channel = get_channel_for_ch_data_idx (i );
412
+ uint8_t ch = get_channel_for_ch_data_idx (i );
413
+
414
+ m_cb .channel_data [i ].channel = ch ;
415
+ m_cb .ch_to_data [ch ] = i ;
398
416
}
399
417
400
418
nrfy_grtc_int_init (NRF_GRTC , GRTC_ALL_INT_MASK , interrupt_priority , false);
@@ -732,6 +750,18 @@ nrfx_err_t nrfx_grtc_syscounter_cc_disable(uint8_t channel)
732
750
return err_code ;
733
751
}
734
752
753
+ void nrfx_grtc_syscounter_cc_abs_set (uint8_t channel , uint64_t val , bool safe_setting )
754
+ {
755
+ m_cb .cc_value [m_cb .ch_to_data [channel ]] = val ;
756
+ if (safe_setting )
757
+ {
758
+ nrfy_grtc_sys_counter_compare_event_disable (NRF_GRTC , channel );
759
+ nrfy_grtc_sys_counter_compare_event_clear (NRF_GRTC , channel );
760
+ }
761
+
762
+ nrfy_grtc_sys_counter_cc_set (NRF_GRTC , channel , val );
763
+ }
764
+
735
765
nrfx_err_t nrfx_grtc_syscounter_cc_absolute_set (nrfx_grtc_channel_t * p_chan_data ,
736
766
uint64_t val ,
737
767
bool enable_irq )
@@ -755,6 +785,7 @@ nrfx_err_t nrfx_grtc_syscounter_cc_absolute_set(nrfx_grtc_channel_t * p_chan_dat
755
785
756
786
if (enable_irq )
757
787
{
788
+ NRFX_ATOMIC_FETCH_OR (& m_cb .read_cc_mask , NRFX_BIT (p_chan_data -> channel ));
758
789
nrfy_grtc_int_enable (NRF_GRTC , GRTC_CHANNEL_TO_BITMASK (p_chan_data -> channel ));
759
790
}
760
791
@@ -764,6 +795,17 @@ nrfx_err_t nrfx_grtc_syscounter_cc_absolute_set(nrfx_grtc_channel_t * p_chan_dat
764
795
return err_code ;
765
796
}
766
797
798
+ void nrfx_grtc_syscounter_cc_rel_set (uint8_t channel ,
799
+ uint32_t val ,
800
+ nrfx_grtc_cc_relative_reference_t reference )
801
+ {
802
+ m_cb .cc_value [m_cb .ch_to_data [channel ]] += val ;
803
+ nrfy_grtc_sys_counter_cc_add_set (NRF_GRTC ,
804
+ channel ,
805
+ val ,
806
+ (nrf_grtc_cc_add_reference_t )reference );
807
+ }
808
+
767
809
nrfx_err_t nrfx_grtc_syscounter_cc_relative_set (nrfx_grtc_channel_t * p_chan_data ,
768
810
uint32_t val ,
769
811
bool enable_irq ,
@@ -793,6 +835,7 @@ nrfx_err_t nrfx_grtc_syscounter_cc_relative_set(nrfx_grtc_channel_t *
793
835
794
836
if (enable_irq )
795
837
{
838
+ NRFX_ATOMIC_FETCH_OR (& m_cb .read_cc_mask , NRFX_BIT (p_chan_data -> channel ));
796
839
nrfy_grtc_int_enable (NRF_GRTC , GRTC_CHANNEL_TO_BITMASK (p_chan_data -> channel ));
797
840
}
798
841
@@ -905,30 +948,61 @@ static void grtc_irq_handler(void)
905
948
uint32_t intpend = nrf_grtc_int_pending_get (NRF_GRTC );
906
949
907
950
while (intpend ) {
908
- uint32_t idx = 31 - NRFX_CLZ (intpend );
951
+ uint8_t idx = ( uint8_t )( 31 - NRFX_CLZ (intpend ) );
909
952
910
953
intpend &= ~NRFX_BIT (idx );
911
- nrf_grtc_event_clear (NRF_GRTC , NRFY_INT_BITPOS_TO_EVENT (idx ));
912
954
913
- if (!NRFX_IS_ENABLED (GRTC_EXT ) || idx < 16 )
955
+ if (!NRFX_IS_ENABLED (GRTC_EXT ) || idx < GRTC_NCC_SIZE )
914
956
{
915
- for (uint32_t i = 0 ; i < NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS ; i ++ )
957
+ uint32_t i = m_cb .ch_to_data [idx ];
958
+
959
+ NRFX_ASSERT (m_cb .channel_data [i ].channel == idx );
960
+
961
+ if (m_cb .channel_data [i ].handler )
916
962
{
917
- if ((m_cb .channel_data [i ].channel == idx ) && m_cb .channel_data [i ].handler )
963
+ uint64_t cc_value ;
964
+
965
+ if (NRFX_ATOMIC_FETCH_AND (& m_cb .read_cc_mask , ~NRFX_BIT (idx )) & NRFX_BIT (idx ))
918
966
{
919
- m_cb .channel_data [i ].handler (idx , m_cb .channel_data [i ].p_context );
920
- break ;
967
+ /* Read CC value only if channel was set using legacy functions. It is done
968
+ * for API backward compatibility. Reading 64 bit value from GRTC is costly
969
+ * and it is avoided if possible.
970
+ */
971
+ cc_value = nrfy_grtc_sys_counter_cc_get (NRF_GRTC , idx );
921
972
}
973
+ else
974
+ {
975
+ /* If CC was set using optimized API then CC is stored in RAM (much faster
976
+ * access).
977
+ */
978
+ cc_value = m_cb .cc_value [i ];
979
+ }
980
+
981
+ /* Check event again (initially checked via INTPEND). It is possible that
982
+ * CC is reconfigured from higher priority context. In that case event
983
+ * might be cleared.
984
+ */
985
+ if (!nrf_grtc_event_check (NRF_GRTC , NRFY_INT_BITPOS_TO_EVENT (idx )))
986
+ {
987
+ break ;
988
+ }
989
+
990
+ nrf_grtc_event_clear (NRF_GRTC , NRFY_INT_BITPOS_TO_EVENT (idx ));
991
+
992
+ m_cb .channel_data [i ].handler (idx , cc_value , m_cb .channel_data [i ].p_context );
993
+ break ;
922
994
}
995
+
923
996
/* Return early as this is the most likely scenario (single CC expiring). */
924
- if (intpend == 0 )
997
+ if (NRFX_IS_ENABLED ( GRTC_EXT ) && ( intpend == 0 ) )
925
998
{
926
999
break ;
927
1000
}
928
1001
}
929
1002
#if NRF_GRTC_HAS_RTCOUNTER
930
1003
if (idx == NRFY_EVENT_TO_INT_BITPOS (NRF_GRTC_EVENT_RTCOMPARE ))
931
1004
{
1005
+ nrf_grtc_event_clear (NRF_GRTC , NRFY_INT_BITPOS_TO_EVENT (idx ));
932
1006
nrfx_grtc_channel_t const * p_channel =
933
1007
& m_cb .channel_data [GRTC_RTCOUNTER_CC_HANDLER_IDX ];
934
1008
if (p_channel -> handler )
@@ -946,6 +1020,7 @@ static void grtc_irq_handler(void)
946
1020
* and set when returning from this state. It can't be cleared inside the ISR
947
1021
* procedure because we rely on it during SYSCOUNTER value reading procedure. */
948
1022
NRFX_LOG_INFO ("Event: NRF_GRTC_EVENT_SYSCOUNTERVALID." );
1023
+ nrf_grtc_event_clear (NRF_GRTC , NRFY_INT_BITPOS_TO_EVENT (idx ));
949
1024
if (m_cb .syscountervalid_handler )
950
1025
{
951
1026
m_cb .syscountervalid_handler (m_cb .syscountervalid_context );
0 commit comments