@@ -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,29 @@ 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_cc_set (NRF_GRTC , channel , val );
759
+ if (nrfy_grtc_sys_counter_compare_event_check (NRF_GRTC , channel ))
760
+ {
761
+ uint64_t now ;
762
+
763
+ nrfx_grtc_syscounter_get (& now );
764
+ if (val > now )
765
+ {
766
+ nrfy_grtc_sys_counter_compare_event_clear (NRF_GRTC , channel );
767
+ }
768
+ }
769
+ }
770
+ else
771
+ {
772
+ nrfy_grtc_sys_counter_cc_set (NRF_GRTC , channel , val );
773
+ }
774
+ }
775
+
735
776
nrfx_err_t nrfx_grtc_syscounter_cc_absolute_set (nrfx_grtc_channel_t * p_chan_data ,
736
777
uint64_t val ,
737
778
bool enable_irq )
@@ -755,6 +796,7 @@ nrfx_err_t nrfx_grtc_syscounter_cc_absolute_set(nrfx_grtc_channel_t * p_chan_dat
755
796
756
797
if (enable_irq )
757
798
{
799
+ NRFX_ATOMIC_FETCH_OR (& m_cb .read_cc_mask , NRFX_BIT (p_chan_data -> channel ));
758
800
nrfy_grtc_int_enable (NRF_GRTC , GRTC_CHANNEL_TO_BITMASK (p_chan_data -> channel ));
759
801
}
760
802
@@ -764,6 +806,17 @@ nrfx_err_t nrfx_grtc_syscounter_cc_absolute_set(nrfx_grtc_channel_t * p_chan_dat
764
806
return err_code ;
765
807
}
766
808
809
+ void nrfx_grtc_syscounter_cc_rel_set (uint8_t channel ,
810
+ uint32_t val ,
811
+ nrfx_grtc_cc_relative_reference_t reference )
812
+ {
813
+ m_cb .cc_value [m_cb .ch_to_data [channel ]] += val ;
814
+ nrfy_grtc_sys_counter_cc_add_set (NRF_GRTC ,
815
+ channel ,
816
+ val ,
817
+ (nrf_grtc_cc_add_reference_t )reference );
818
+ }
819
+
767
820
nrfx_err_t nrfx_grtc_syscounter_cc_relative_set (nrfx_grtc_channel_t * p_chan_data ,
768
821
uint32_t val ,
769
822
bool enable_irq ,
@@ -793,6 +846,7 @@ nrfx_err_t nrfx_grtc_syscounter_cc_relative_set(nrfx_grtc_channel_t *
793
846
794
847
if (enable_irq )
795
848
{
849
+ NRFX_ATOMIC_FETCH_OR (& m_cb .read_cc_mask , NRFX_BIT (p_chan_data -> channel ));
796
850
nrfy_grtc_int_enable (NRF_GRTC , GRTC_CHANNEL_TO_BITMASK (p_chan_data -> channel ));
797
851
}
798
852
@@ -905,30 +959,61 @@ static void grtc_irq_handler(void)
905
959
uint32_t intpend = nrf_grtc_int_pending_get (NRF_GRTC );
906
960
907
961
while (intpend ) {
908
- uint32_t idx = 31 - NRFX_CLZ (intpend );
962
+ uint8_t idx = ( uint8_t )( 31 - NRFX_CLZ (intpend ) );
909
963
910
964
intpend &= ~NRFX_BIT (idx );
911
- nrf_grtc_event_clear (NRF_GRTC , NRFY_INT_BITPOS_TO_EVENT (idx ));
912
965
913
- if (!NRFX_IS_ENABLED (GRTC_EXT ) || idx < 16 )
966
+ if (!NRFX_IS_ENABLED (GRTC_EXT ) || idx < GRTC_NCC_SIZE )
914
967
{
915
- for (uint32_t i = 0 ; i < NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS ; i ++ )
968
+ uint32_t i = m_cb .ch_to_data [idx ];
969
+
970
+ NRFX_ASSERT (m_cb .channel_data [i ].channel == idx );
971
+
972
+ if (m_cb .channel_data [i ].handler )
916
973
{
917
- if ((m_cb .channel_data [i ].channel == idx ) && m_cb .channel_data [i ].handler )
974
+ uint64_t cc_value ;
975
+
976
+ if (NRFX_ATOMIC_FETCH_AND (& m_cb .read_cc_mask , ~NRFX_BIT (idx )) & NRFX_BIT (idx ))
918
977
{
919
- m_cb .channel_data [i ].handler (idx , m_cb .channel_data [i ].p_context );
920
- break ;
978
+ /* Read CC value only if channel was set using legacy functions. It is done
979
+ * for API backward compatibility. Reading 64 bit value from GRTC is costly
980
+ * and it is avoided if possible.
981
+ */
982
+ cc_value = nrfy_grtc_sys_counter_cc_get (NRF_GRTC , idx );
921
983
}
984
+ else
985
+ {
986
+ /* If CC was set using optimized API then CC is stored in RAM (much faster
987
+ * access).
988
+ */
989
+ cc_value = m_cb .cc_value [i ];
990
+ }
991
+
992
+ /* Check event again (initially checked via INTPEND). It is possible that
993
+ * CC is reconfigured from higher priority context. In that case event
994
+ * might be cleared.
995
+ */
996
+ if (!nrf_grtc_event_check (NRF_GRTC , NRFY_INT_BITPOS_TO_EVENT (idx )))
997
+ {
998
+ break ;
999
+ }
1000
+
1001
+ nrf_grtc_event_clear (NRF_GRTC , NRFY_INT_BITPOS_TO_EVENT (idx ));
1002
+
1003
+ m_cb .channel_data [i ].handler (idx , cc_value , m_cb .channel_data [i ].p_context );
1004
+ break ;
922
1005
}
1006
+
923
1007
/* Return early as this is the most likely scenario (single CC expiring). */
924
- if (intpend == 0 )
1008
+ if (NRFX_IS_ENABLED ( GRTC_EXT ) && ( intpend == 0 ) )
925
1009
{
926
1010
break ;
927
1011
}
928
1012
}
929
1013
#if NRF_GRTC_HAS_RTCOUNTER
930
1014
if (idx == NRFY_EVENT_TO_INT_BITPOS (NRF_GRTC_EVENT_RTCOMPARE ))
931
1015
{
1016
+ nrf_grtc_event_clear (NRF_GRTC , NRFY_INT_BITPOS_TO_EVENT (idx ));
932
1017
nrfx_grtc_channel_t const * p_channel =
933
1018
& m_cb .channel_data [GRTC_RTCOUNTER_CC_HANDLER_IDX ];
934
1019
if (p_channel -> handler )
@@ -946,6 +1031,7 @@ static void grtc_irq_handler(void)
946
1031
* and set when returning from this state. It can't be cleared inside the ISR
947
1032
* procedure because we rely on it during SYSCOUNTER value reading procedure. */
948
1033
NRFX_LOG_INFO ("Event: NRF_GRTC_EVENT_SYSCOUNTERVALID." );
1034
+ nrf_grtc_event_clear (NRF_GRTC , NRFY_INT_BITPOS_TO_EVENT (idx ));
949
1035
if (m_cb .syscountervalid_handler )
950
1036
{
951
1037
m_cb .syscountervalid_handler (m_cb .syscountervalid_context );
0 commit comments