This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to count timer overflows on a synchronized clock?

I am working with a modified project based on the time sync example using two nRF52832 DKs.

I want to capture how many times the timer overflows on the receiving board, while being synchronized to the sending board.

I created high_freq_timer[2] to be NRF_TIMER4 and configured it in counter mode, just after sync_timer_start

m_params.high_freq_timer[2]->TASKS_STOP  = 1;
m_params.high_freq_timer[2]->TASKS_CLEAR = 1;
m_params.high_freq_timer[2]->MODE = TIMER_MODE_MODE_Counter;
m_params.high_freq_timer[2]->CC[0]       = 0;
m_params.high_freq_timer[2]->TASKS_START = 1;

I added a PPI connection on channel 5 to fire NRF_TIMER4 inside ppi_configure

NRF_PPI->CHENCLR      = (1 << 5);
NRF_PPI->CH[5].EEP = (uint32_t) &m_params.high_freq_timer[0]->EVENTS_COMPARE[2];
NRF_PPI->CH[5].TEP = (uint32_t) &m_params.high_freq_timer[2]->TASKS_COUNT;
NRF_PPI->CHENSET         = (1 << 5);

This fires whenever the NRF_TIMER2 rolls over on its synchronized value (read on to discover why this doesn't work)

// Write offset to timer compare register
m_params.high_freq_timer[0]->CC[2] = (TIMER_MAX_VAL - timer_offset);

I also changed NRF_TIMER2 to be 24 bits instead of 16 bits.

m_params.high_freq_timer[0]->BITMODE     = TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos;

set the max value

#define TIMER_MAX_VAL (0xFFFFFF)

Separated the handler for button 4 to capture and print the value. I'm reading it over UART, but NRF_LOG_INFO while debugging probably works too.

case BSP_EVENT_KEY_3:
{
    NRF_TIMER4->TASKS_CAPTURE[0] = 1;
    printf("%d\r\n", NRF_TIMER4->CC[0]);
}
break;

This works properly when the clock is not being synchronized to the sender. When the sender starts sending synch packets, the receiver clock resets barely earlier or later (later = wait until the new cycle then reset very fast)

If I print out some of the timer offsets that the receiving board's timer is resetting it's count at, I see it sometimes causes the timer to reset extremely rapidly (depending on if the clock is ahead or behind the sender) resulting in a double increase on the counter because the counter is counting whenever the timer compare value event is fired and the timer reset.

16777214
16777213
1
2
16777211
1
16777213
5

How can I best count this synchronized clock's overflows (not whenever it actually resets as the current implementation does, but at the overflow rate of the sender's clock) without getting extra counts?

  • Hi Nick,

    I'm not sure I fully understand the question, and might need some further background information to understand better if the tip below doesn't make sense.

    When a timing packet is received from a peer device the local synchronization timer is reset/cleared slightly ahead of, or slightly after, the wraparound value (2^24 in this case). As you write, this is done by using CC[2] to trigger the TIMER.CLEAR task.

    In the synchronization code, a PPI channel is used to trigger TIMER.CLEAR from the CC[2] compare event, and another PPI channel is used to disable the first PPI channel such that it only clears the timer once. Disabling PPI channels via other PPI channels is done using PPI Channel Groups.

    In your case, I recommend adding PPI channel 5 to the PPI Channel group which is disabled when CC[2] fires. The behavior should be the following:

    1. A timer packet is received, and an local sync timer adjustment is determined to be required
    2. CC[2] is updated with the adjustment factor
    3. PPI.CHENSET is set to enable all relevant PPI channels, including channel 5 (only update the channel mask value. Adding a second write to the CHENSET register will allow race conditions).
    4. When CC[2] fires the timer will be cleared as normal, PPI channel 5 will cause TIMER4 counter to increment, and then the PPI group containing all relevant channels will be disabled such that CC[2] doesn't continuously trigger this behavior.

    Hope this helps!

    Audun

Related