Skip to content

Commit 43bc959

Browse files
committed
nrfx: drivers: grtc: Add function dedicated for nrf_grtc_timer
Add functions that improves performance of nrf_grtc_timer: - Channel allocation with callback. Previously callback is written on every CC val setting which is redundant - Function for setting CCADD register - Function for setting CC register Signed-off-by: Krzysztof Chruściński <[email protected]>
1 parent 973d387 commit 43bc959

File tree

2 files changed

+132
-6
lines changed

2 files changed

+132
-6
lines changed

nrfx/drivers/include/nrfx_grtc.h

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,9 @@ extern "C" {
5252
* @brief GRTC driver instance compare handler type.
5353
*
5454
* @param[in] id Channel ID.
55-
* @param[in] cc_value Compare value.
5655
* @param[in] p_context User context.
5756
*/
58-
typedef void (*nrfx_grtc_cc_handler_t)(int32_t id, uint64_t cc_value, void * p_context);
57+
typedef void (*nrfx_grtc_cc_handler_t)(int32_t id, void * p_context);
5958

6059
#if NRFY_GRTC_HAS_EXTENDED || defined(__NRFX_DOXYGEN__)
6160
/**
@@ -158,6 +157,7 @@ nrfx_err_t nrfx_grtc_sleep_configuration_get(nrfx_grtc_sleep_config_t * p_sleep_
158157
* @brief Function for allocating the GRTC capture/compare channel.
159158
*
160159
* @note Function is thread safe as it uses @ref nrfx_flag32_alloc.
160+
* @note This function marks the specified @p channel as used.
161161
* @note Routines that allocate and free the GRTC channels are independent
162162
* from the rest of the driver. In particular, the driver does not need
163163
* to be initialized when this function is called.
@@ -169,6 +169,25 @@ nrfx_err_t nrfx_grtc_sleep_configuration_get(nrfx_grtc_sleep_config_t * p_sleep_
169169
*/
170170
nrfx_err_t nrfx_grtc_channel_alloc(uint8_t * p_channel);
171171

172+
/**
173+
* @brief Function for allocating the GRTC capture/compare channel for callback
174+
*
175+
* Function gets callback which shall be used for that channel. Since channel will
176+
* be used with callback, interrupt is enabled for that channel.
177+
*
178+
* @note Function is thread safe as it uses @ref nrfx_flag32_alloc.
179+
*
180+
* @param[out] p_channel Pointer to the capture/compare channel.
181+
* @param[in] handler User handler called when channel expires.
182+
* @param[in] p_context Context passed to the callback.
183+
*
184+
* @retval NRFX_SUCCESS Allocation was successful.
185+
* @retval NRFX_ERROR_NO_MEM No resource available.
186+
*/
187+
nrfx_err_t nrfx_grtc_channel_cb_alloc(uint8_t * p_channel,
188+
nrfx_grtc_cc_handler_t handler,
189+
void *p_context);
190+
172191
/**
173192
* @brief Function for freeing the GRTC capture/compare channel.
174193
*
@@ -281,22 +300,27 @@ void nrfx_grtc_syscountervalid_int_disable(void);
281300
* @brief Function for starting the 1 MHz SYSCOUNTER.
282301
*
283302
* @note This function automatically allocates and marks as used the special-purpose main
284-
* capture/compare channel. It is available only for GRTC manager.
303+
* capture/compare channel. Interrupt for that channel is enabled.
304+
* It is available only for GRTC manager.
285305
*
286306
* @note Use auxiliary structure of type @ref nrfx_grtc_channel_t when working with SYSCOUNTER.
287307
*
288308
* @param[in] busy_wait True if wait for synchronization operation is to be performed,
289309
* false otherwise.
290310
* @param[out] p_main_cc_channel Pointer to the main capture/compare channel.
311+
* @param[in] handler Handler.
312+
* @param[in] p_context User context passed to the callback.
291313
*
292314
* @retval NRFX_SUCCESS Starting was successful.
293315
* @retval NRFX_ERROR_NO_MEM No resource available to allocate main channel.
294316
* @retval NRFX_ERROR_ALREADY The GRTC is already running.
295317
* @retval NRFX_ERROR_TIMEOUT The SYSCOUNTER failed to start due to a timeout.
296318
*/
297319

298-
nrfx_err_t nrfx_grtc_syscounter_start(bool busy_wait, uint8_t * p_main_cc_channel);
299-
320+
nrfx_err_t nrfx_grtc_syscounter_start(bool busy_wait,
321+
uint8_t * p_main_cc_channel,
322+
nrfx_grtc_cc_handler_t handler,
323+
void *p_context);
300324
/**
301325
* @brief Function for performing an action for the GRTC.
302326
*
@@ -359,6 +383,22 @@ nrfx_err_t nrfx_grtc_syscounter_cc_absolute_set(nrfx_grtc_channel_t * p_chan_dat
359383
uint64_t val,
360384
bool enable_irq);
361385

386+
/**
387+
* @brief Function for setting the absolute compare value for the SYSCOUNTER.
388+
*
389+
* Function must be called with interrupts locked. If %p safe_setting is true then
390+
* it means that previous CC for that channel did not yet expired and it
391+
* was set to a value earlier than %p val so there is a chance that it will
392+
* expire during setting the new value. In that case compare event may be misinterpreted.
393+
* Slower but safe procedure is used in that case. If %p safe_setting is false then
394+
* function just sets new CC value.
395+
*
396+
* @param[in] channel Channel.
397+
* @param[in] val Absolute value to be set in the compare register.
398+
* @param[in] safe_setting Use safe procedure if true or just set CC to a new value if false.
399+
*/
400+
void nrfx_grtc_syscounter_cc_abs_set(uint8_t channel, uint64_t val, bool safe_setting);
401+
362402
/**
363403
* @brief Function for setting the relative compare value for the SYSCOUNTER.
364404
*
@@ -379,6 +419,22 @@ nrfx_err_t nrfx_grtc_syscounter_cc_relative_set(nrfx_grtc_channel_t *
379419
bool enable_irq,
380420
nrfx_grtc_cc_relative_reference_t reference);
381421

422+
/**
423+
* @brief Function for setting the relative compare value for the SYSCOUNTER.
424+
*
425+
* Function just sets CCADD value and does not attempt to enable or disable the interrupt.
426+
* It assumes that expected channel configuration is done prior to that call.
427+
* Function assumes that previously used CC value has already expired so new value
428+
* can be safely set without a risk of spurious CC expiration.
429+
*
430+
* @param[in] channel Channel.
431+
* @param[in] val Relative value to be set in the CCADD register.
432+
* @param[in] reference Reference. Current counter value or current CC value.
433+
*/
434+
void nrfx_grtc_syscounter_cc_rel_set(uint8_t channel,
435+
uint32_t val,
436+
nrfx_grtc_cc_relative_reference_t reference);
437+
382438
/**
383439
* @brief Function for disabling the SYSCOUNTER compare interrupt.
384440
*
@@ -539,6 +595,15 @@ NRFX_STATIC_INLINE bool nrfx_grtc_sys_counter_cc_enable_check(uint8_t channel);
539595
*/
540596
NRFX_STATIC_INLINE bool nrfx_grtc_syscounter_compare_event_check(uint8_t channel);
541597

598+
/**
599+
* @brief Function for retrieving CC value.
600+
*
601+
* @param[in] channel Compare channel.
602+
*
603+
* @return Value read from CC register.
604+
*/
605+
NRFX_STATIC_INLINE uint64_t nrfx_grtc_sys_counter_cc_get(uint8_t channel);
606+
542607
#if NRF_GRTC_HAS_RTCOUNTER || defined(__NRFX_DOXYGEN__)
543608
/**
544609
* @brief Function for reading the GRTC RTCOUNTER value.
@@ -590,6 +655,11 @@ NRFX_STATIC_INLINE bool nrfx_grtc_syscounter_compare_event_check(uint8_t channel
590655
return nrfy_grtc_sys_counter_compare_event_check(NRF_GRTC, channel);
591656
}
592657

658+
NRFX_STATIC_INLINE uint64_t nrfx_grtc_sys_counter_cc_get(uint8_t channel)
659+
{
660+
return nrfy_grtc_sys_counter_cc_get(NRF_GRTC, channel);
661+
}
662+
593663
#if NRF_GRTC_HAS_RTCOUNTER
594664
NRFX_STATIC_INLINE uint64_t nrfx_grtc_rtcounter_get(void)
595665
{

nrfx/drivers/src/nrfx_grtc.c

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,24 @@ nrfx_err_t nrfx_grtc_syscounter_get(uint64_t * p_counter)
306306
return err_code;
307307
}
308308

309+
nrfx_err_t nrfx_grtc_channel_cb_alloc(uint8_t * p_channel,
310+
nrfx_grtc_cc_handler_t handler,
311+
void *p_context)
312+
{
313+
nrfx_err_t err_code = nrfx_flag32_alloc(&m_cb.available_channels, p_channel);
314+
if (err_code != NRFX_SUCCESS) {
315+
return err_code;
316+
}
317+
uint8_t ch_data_idx = get_ch_data_index_for_channel(*p_channel);
318+
319+
m_cb.channel_data[ch_data_idx].handler = handler;
320+
m_cb.channel_data[ch_data_idx].p_context = p_context;
321+
m_cb.channel_data[ch_data_idx].channel = *p_channel;
322+
nrfy_grtc_int_enable(NRF_GRTC, GRTC_CHANNEL_TO_BITMASK(*p_channel));
323+
324+
return err_code;
325+
}
326+
309327
nrfx_err_t nrfx_grtc_channel_alloc(uint8_t * p_channel)
310328
{
311329
NRFX_ASSERT(p_channel);
@@ -532,7 +550,10 @@ nrfx_err_t nrfx_grtc_rtcounter_cc_absolute_set(nrfx_grtc_rtcounter_handler_data_
532550
#endif // NRF_GRTC_HAS_RTCOUNTER
533551

534552
#if NRFY_GRTC_HAS_EXTENDED
535-
nrfx_err_t nrfx_grtc_syscounter_start(bool busy_wait, uint8_t * p_main_cc_channel)
553+
nrfx_err_t nrfx_grtc_syscounter_start(bool busy_wait,
554+
uint8_t * p_main_cc_channel,
555+
nrfx_grtc_cc_handler_t handler,
556+
void *p_context)
536557
{
537558
NRFX_ASSERT(m_cb.state == NRFX_DRV_STATE_INITIALIZED);
538559
NRFX_ASSERT(p_main_cc_channel);
@@ -551,6 +572,9 @@ nrfx_err_t nrfx_grtc_syscounter_start(bool busy_wait, uint8_t * p_main_cc_channe
551572
}
552573

553574
*p_main_cc_channel = MAIN_GRTC_CC_CHANNEL;
575+
m_cb.channel_data[0].handler = handler;
576+
m_cb.channel_data[0].p_context = p_context;
577+
nrfy_grtc_int_enable(NRF_GRTC, GRTC_CHANNEL_TO_BITMASK(*p_main_cc_channel));
554578
m_cb.available_channels &= ~GRTC_CHANNEL_TO_BITMASK(MAIN_GRTC_CC_CHANNEL);
555579
channel_used_mark(MAIN_GRTC_CC_CHANNEL);
556580
NRFX_LOG_INFO("GRTC channel %u allocated.", m_cb.channel_data[0].channel);
@@ -732,6 +756,28 @@ nrfx_err_t nrfx_grtc_syscounter_cc_disable(uint8_t channel)
732756
return err_code;
733757
}
734758

759+
void nrfx_grtc_syscounter_cc_abs_set(uint8_t channel, uint64_t val, bool safe_setting)
760+
{
761+
if (safe_setting)
762+
{
763+
nrfy_grtc_sys_counter_cc_set(NRF_GRTC, channel, val);
764+
if (nrfy_grtc_sys_counter_compare_event_check(NRF_GRTC, channel))
765+
{
766+
uint64_t now;
767+
768+
nrfx_grtc_syscounter_get(&now);
769+
if (val > now)
770+
{
771+
nrfy_grtc_sys_counter_compare_event_clear(NRF_GRTC, channel);
772+
}
773+
}
774+
}
775+
else
776+
{
777+
nrfy_grtc_sys_counter_cc_set(NRF_GRTC, channel, val);
778+
}
779+
}
780+
735781
nrfx_err_t nrfx_grtc_syscounter_cc_absolute_set(nrfx_grtc_channel_t * p_chan_data,
736782
uint64_t val,
737783
bool enable_irq)
@@ -764,6 +810,16 @@ nrfx_err_t nrfx_grtc_syscounter_cc_absolute_set(nrfx_grtc_channel_t * p_chan_dat
764810
return err_code;
765811
}
766812

813+
void nrfx_grtc_syscounter_cc_rel_set(uint8_t channel,
814+
uint32_t val,
815+
nrfx_grtc_cc_relative_reference_t reference)
816+
{
817+
nrfy_grtc_sys_counter_cc_add_set(NRF_GRTC,
818+
channel,
819+
val,
820+
(nrf_grtc_cc_add_reference_t)reference);
821+
}
822+
767823
nrfx_err_t nrfx_grtc_syscounter_cc_relative_set(nrfx_grtc_channel_t * p_chan_data,
768824
uint32_t val,
769825
bool enable_irq,

0 commit comments

Comments
 (0)