Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1248514

Browse files
committedJul 24, 2022
Updates to reduce timing jitter
1 parent f005e47 commit 1248514

File tree

2 files changed

+28
-23
lines changed

2 files changed

+28
-23
lines changed
 

‎app_timer.c

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,14 @@ static inline app_timer_running_count_t _ticks_until_expiry(app_timer_running_co
150150
* list is maintained (the next timer to expire must always be the head of the list).
151151
*
152152
* @note The #start_counts and #total_counts fields of the timer must be set before calling
153-
* this function
153+
* this function. #start_counts should be set to the timestamp in counts when the timer
154+
* was added via #app_timer_start, and #total_counts should be set to the timer period
155+
* in counts.
154156
*
155157
* @param timer Pointer to timer instance to insert
158+
* @param now Current timestamp in timer counts
156159
*/
157-
static void _insert_active_timer(app_timer_t *timer)
160+
static void _insert_active_timer(app_timer_t *timer, app_timer_running_count_t now)
158161
{
159162
// Set timer state to active
160163
timer->flags &= ~FLAGS_STATE_MASK;
@@ -177,9 +180,6 @@ static void _insert_active_timer(app_timer_t *timer)
177180
return;
178181
}
179182

180-
// timer->start_counts is assumed to be set to the current timestamp
181-
app_timer_running_count_t now = timer->start_counts;
182-
183183
app_timer_t *curr = _active_timers.head;
184184

185185
/* Pending timers are maintained as a doubly-linked list, in ascending order
@@ -313,8 +313,15 @@ void app_timer_target_count_reached(void)
313313
app_timer_int_status_t int_status = 0u;
314314
_hw_model->set_interrupts_enabled(false, &int_status);
315315

316+
// The tick on which the head active timer should have expired
317+
app_timer_running_count_t expiry_count = _running_timer_count + _last_timer_period;
318+
319+
// Update _running_timer_count with ticks elapsed since last update
320+
#ifdef APP_TIMER_FREERUNNING_COUNTER
321+
_running_timer_count += (_hw_model->read_timer_counts() - _counts_after_last_start);
322+
#else
316323
_running_timer_count += (app_timer_running_count_t) _last_timer_period;
317-
app_timer_running_count_t now = _running_timer_count;
324+
#endif // APP_TIMER_FREERUNNING_COUNTER
318325

319326
// Stop the timer counter, re-start it to time how long it takes to handle all expired timers
320327
#ifndef APP_TIMER_RECONFIG_WITHOUT_STOPPING
@@ -327,7 +334,7 @@ void app_timer_target_count_reached(void)
327334
_counts_after_last_start = _hw_model->read_timer_counts();
328335

329336
// Remove all expired timers from the active list, and run their handlers
330-
while ((NULL != _active_timers.head) && (_ticks_until_expiry(now, _active_timers.head) == 0u))
337+
while ((NULL != _active_timers.head) && (_ticks_until_expiry(expiry_count, _active_timers.head) == 0u))
331338
{
332339
app_timer_t *curr = _active_timers.head;
333340

@@ -367,38 +374,35 @@ void app_timer_target_count_reached(void)
367374
{
368375
/* Timer is repeating, and was not-restarted or stopped by the handler,
369376
* so must be re-inserted with a new start time */
370-
curr->start_counts = now;
371-
_insert_active_timer(curr);
377+
curr->start_counts = expiry_count;
378+
_insert_active_timer(curr, _total_timer_counts());
372379
}
373380
}
374381

375-
// Update running timer count with time taken to run expired handlers
376-
_running_timer_count += (_hw_model->read_timer_counts() - _counts_after_last_start);
377-
now = _running_timer_count;
378-
#ifndef APP_TIMER_RECONFIG_WITHOUT_STOPPING
379-
_hw_model->set_timer_running(false);
380-
#endif // APP_TIMER_RECONFIG_WITHOUT_STOPPING
381-
382382
if (NULL == _active_timers.head)
383383
{
384-
// No more active timers, don't re-start the counter
384+
// No more active timers, stop the counter
385385
_running_timer_count = 0u;
386-
#ifdef APP_TIMER_RECONFIG_WITHOUT_STOPPING
387-
/* If we didn't already stop the counter to set a new timer period,
388-
* and there are no more active timers, then we should stop the counter now */
389386
_hw_model->set_timer_running(false);
390-
#endif // APP_TIMER_RECONFIG_WITHOUT_STOPPING
391387
}
392388
else
393389
{
390+
// Update running timer count with time taken to run expired handlers
391+
_running_timer_count += (_hw_model->read_timer_counts() - _counts_after_last_start);
392+
394393
// Configure timer for the next expiration and re-start
395-
app_timer_running_count_t ticks_until_expiry = _ticks_until_expiry(now, _active_timers.head);
394+
app_timer_running_count_t ticks_until_expiry = _ticks_until_expiry(_running_timer_count, _active_timers.head);
396395

397396
/* If the head timer should have already expired (it expired while we were handling
398397
* other expired timers in the loop above), just configure the hardware for 1 tick,
399398
* and the head timer will be handled in the next call (although it does have the downside
400399
* that the head timer will expire at least 1 tick late) */
401400
bool expiry_overflow = (ticks_until_expiry == 0u);
401+
402+
#ifndef APP_TIMER_RECONFIG_WITHOUT_STOPPING
403+
_hw_model->set_timer_running(false);
404+
#endif // APP_TIMER_RECONFIG_WITHOUT_STOPPING
405+
402406
_configure_timer(expiry_overflow ? 1u : ticks_until_expiry);
403407
#ifdef APP_TIMER_STATS_ENABLE
404408
_stats.num_expiry_overflows += (uint32_t) expiry_overflow;
@@ -509,7 +513,7 @@ app_timer_error_e app_timer_start(app_timer_t *timer, app_timer_period_t time_fr
509513
}
510514

511515
// Insert timer into list
512-
_insert_active_timer(timer);
516+
_insert_active_timer(timer, timer->start_counts);
513517

514518
/* If this is the new head of the list, we need to re-configure the hardware timer/counter */
515519
if ((timer == _active_timers.head) && !_inside_target_count_reached)

‎app_timer_api.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ extern "C" {
7373
#define APP_TIMER_INT_UINT32 // Store interrupt status value in 32 bits by default
7474
#endif
7575

76+
7677
/**
7778
* Datatype used to represent the period for a timer (e.g. the 'time_from_now' parameter
7879
* passed to app_timer_start).

0 commit comments

Comments
 (0)
Please sign in to comment.