Skip to content

Commit 973d387

Browse files
committed
nrfx: drivers: grtc: Use INTPEND in the interrupt handler
Use INTPEND in the interrupt handler to optimize handler execution. Do not read CC value from GRTC registers before calling the user handler. User can read that if it is needed. Reading GRTC registers is costly and should be avoided if possible. Signed-off-by: Krzysztof Chruściński <[email protected]>
1 parent c4c6c6d commit 973d387

File tree

1 file changed

+42
-48
lines changed

1 file changed

+42
-48
lines changed

nrfx/drivers/src/nrfx_grtc.c

Lines changed: 42 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -896,69 +896,63 @@ nrfx_err_t nrfx_grtc_syscounter_cc_value_read(uint8_t channel, uint64_t * p_val)
896896
return err_code;
897897
}
898898

899+
#if NRF_GRTC_HAS_RTCOUNTER || (NRFY_GRTC_HAS_EXTENDED && NRFY_GRTC_HAS_SYSCOUNTERVALID)
900+
#define GRTC_EXT 1
901+
#endif
902+
899903
static void grtc_irq_handler(void)
900904
{
901-
uint32_t evt_to_process = GRTC_CHANNEL_MASK_TO_INT_MASK(allocated_channels_mask_get() &
902-
used_channels_mask_get());
903-
#if NRF_GRTC_HAS_RTCOUNTER
904-
evt_to_process |= (GRTC_NON_SYSCOMPARE_INT_MASK & ~NRF_GRTC_INT_SYSCOUNTERVALID_MASK);
905-
#endif
906-
uint32_t event_mask = nrfy_grtc_events_process(NRF_GRTC, evt_to_process);
907-
uint32_t active_int_mask = nrfy_grtc_int_enable_check(NRF_GRTC, event_mask);
908-
nrf_grtc_event_t event;
905+
uint32_t intpend = nrf_grtc_int_pending_get(NRF_GRTC);
909906

910-
for (uint32_t i = 0; i < NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS; i++)
911-
{
912-
uint8_t channel = m_cb.channel_data[i].channel;
907+
while (intpend) {
908+
uint32_t idx = 31 - NRFX_CLZ(intpend);
909+
910+
intpend &= ~NRFX_BIT(idx);
911+
nrf_grtc_event_clear(NRF_GRTC, NRFY_INT_BITPOS_TO_EVENT(idx));
913912

914-
event = nrfy_grtc_sys_counter_compare_event_get(channel);
915-
if (active_int_mask & NRFY_EVENT_TO_INT_BITMASK(event))
913+
if (!NRFX_IS_ENABLED(GRTC_EXT) || idx < 16)
916914
{
917-
NRFX_LOG_INFO("Event: NRF_GRTC_EVENT_COMPARE_%d.", channel);
918-
if (m_cb.channel_data[i].handler)
915+
for (uint32_t i = 0; i < NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS; i++)
919916
{
920-
m_cb.channel_data[i].handler((int32_t)channel,
921-
nrfy_grtc_sys_counter_cc_get(NRF_GRTC, channel),
922-
m_cb.channel_data[i].p_context);
917+
if ((m_cb.channel_data[i].channel == idx) && m_cb.channel_data[i].handler)
918+
{
919+
m_cb.channel_data[i].handler(idx, m_cb.channel_data[i].p_context);
920+
break;
921+
}
922+
}
923+
/* Return early as this is the most likely scenario (single CC expiring). */
924+
if (intpend == 0)
925+
{
926+
break;
923927
}
924928
}
925-
}
926929
#if NRF_GRTC_HAS_RTCOUNTER
927-
if (active_int_mask & NRF_GRTC_INT_RTCOMPARE_MASK)
928-
{
929-
NRFX_LOG_INFO("Event: NRF_GRTC_EVENT_RTCOMPARE.");
930-
nrfx_grtc_channel_t const * p_channel = &m_cb.channel_data[GRTC_RTCOUNTER_CC_HANDLER_IDX];
931-
if (p_channel->handler)
930+
if (idx == NRFY_EVENT_TO_INT_BITPOS(NRF_GRTC_EVENT_RTCOMPARE))
932931
{
933-
p_channel->handler((int32_t)GRTC_RTCOUNTER_COMPARE_CHANNEL,
934-
nrfy_grtc_rt_counter_cc_get(NRF_GRTC),
935-
p_channel->p_context);
936-
}
937-
}
938-
939-
if (active_int_mask & NRF_GRTC_INT_RTCOMPARESYNC_MASK)
940-
{
941-
NRFX_LOG_INFO("Event: NRF_GRTC_EVENT_RTCOMPARESYNC.");
942-
if (m_cb.rtcomparesync_handler)
943-
{
944-
m_cb.rtcomparesync_handler(m_cb.rtcomparesync_context);
945-
}
946-
}
932+
nrfx_grtc_channel_t const * p_channel =
933+
&m_cb.channel_data[GRTC_RTCOUNTER_CC_HANDLER_IDX];
934+
if (p_channel->handler)
935+
{
936+
p_channel->handler((int32_t)GRTC_RTCOUNTER_COMPARE_CHANNEL,
937+
nrfy_grtc_rt_counter_cc_get(NRF_GRTC),
938+
p_channel->p_context);
939+
}
940+
}
947941
#endif // NRF_GRTC_HAS_RTCOUNTER
948942
#if NRFY_GRTC_HAS_EXTENDED && NRFY_GRTC_HAS_SYSCOUNTERVALID
949-
/* The SYSCOUNTERVALID bit is automatically cleared when GRTC goes into sleep state and set
950-
* when returning from this state. It can't be cleared inside the ISR procedure because we rely
951-
* on it during SYSCOUNTER value reading procedure. */
952-
if (nrfy_grtc_event_check(NRF_GRTC, NRF_GRTC_EVENT_SYSCOUNTERVALID) &&
953-
nrfy_grtc_int_enable_check(NRF_GRTC, NRF_GRTC_INT_SYSCOUNTERVALID_MASK))
954-
{
955-
NRFX_LOG_INFO("Event: NRF_GRTC_EVENT_SYSCOUNTERVALID.");
956-
if (m_cb.syscountervalid_handler)
943+
if (idx == NRFY_EVENT_TO_INT_BITPOS(NRF_GRTC_EVENT_SYSCOUNTERVALID))
957944
{
958-
m_cb.syscountervalid_handler(m_cb.syscountervalid_context);
945+
/* The SYSCOUNTERVALID bit is automatically cleared when GRTC goes into sleep state
946+
* and set when returning from this state. It can't be cleared inside the ISR
947+
* procedure because we rely on it during SYSCOUNTER value reading procedure. */
948+
NRFX_LOG_INFO("Event: NRF_GRTC_EVENT_SYSCOUNTERVALID.");
949+
if (m_cb.syscountervalid_handler)
950+
{
951+
m_cb.syscountervalid_handler(m_cb.syscountervalid_context);
952+
}
959953
}
960-
}
961954
#endif // NRFY_GRTC_HAS_EXTENDED && NRFY_GRTC_HAS_SYSCOUNTERVALID
955+
}
962956
}
963957

964958
void nrfx_grtc_irq_handler(void)

0 commit comments

Comments
 (0)