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

Best way to implement system clock on nRF51

Hi everybody,

a while ago I used the approach proposed here devzone.nordicsemi.com/.../ to keep the date and time on a NRF51822 device while using Softdevice S110 and the Timeslot advertiser-scanner (github.com/.../nRF51-multi-role-conn-observer-advertiser).

In practice I created an app_timer timer that executes every 250 milliseconds (this is the resolution I wanted) and inside the handler I incremented some variables accordingly to keep date and time. The problem is that I noticed that the time was not accurate, it was wrong, sometimes of several seconds, already after 1 hour. Here is the first question: I think that the time was wrong mainly because the app_timer handler gets delayed by the BLE stack, am I correct?

My idea to improve this is to connect an RTC1 COMPARE event to the TIMER1 COUNT task through PPI. The RTC1 will be configured to fire the event every second. This way I could keep the time in TIMER1 as a Unix timestamp (seconds since 1970-01-01) and I could read the number of milliseconds from RTC1 (I will use the number of ticks together with the prescaler to compute the milliseconds). This way there is no software handler involved and therefore it could not get delayed, is it correct? Is this going to be more precise than the solution using the app_timer? Will this solution consume more power? Do I need to keep on the 16MHz clock?

The implication of this solution is that I cannot use the app_timer library anymore or I could modify it to connect the RTC COMPARE event with the TIMER COUNT task and this should not interfere with the normal operation of the library, right?

I could try to implement the solution but since I am not sure it will work I would like some feedback from you.

Thanks a lot. Alessandro

  • All your assumptions are correct. You new solution will work without the interference from software and the Timer in counter mode will keep the counter value ticking with the max possible precision. As you have already guessed, Timer needs 16MHz clock, so the power consumption will go rapidly high if you keep this clock running all the time. One posssible way (instead of using Timer1) with little better precision than the existing app_timer is to implement your own RTC1 interrupt handler with APP_PRIORITY_HIGH and try to keep the interrupt handling as fast and short as possible. Then the precision would increase much (even though not as precise as your other solution with PPI, but atleast it will not require power hungry 16MHz clock)

  • Does the hfclk get requested when the timer is in counter mode? In counter mode it does not need a clock to increment, right? It uses an external trigger, in this case the rtc.

  • Hi Aryan, thanks for your answer. As mentioned by Martijn, I am also wondering if the timer needs the hfclk even when in counter mode. From the reference manual it seems it is not like that, but it is not specified.

  • I modified app_timer to track overflow events, so can build up a timestamp from 'overflows' and the counter value. I have a timestamp_t that is seconds and 32768hz ticks, which I use for all my timekeeping code.

    The 32768Hz clock source should be reasonably accurate. One gotcha is app_timer will turn off the RTC when no timers are pendings, so you need least one pending timer at all times to prevent it from turning off the clock (I have an app_timer that I use as part of my watchdog code, that keeps the RTC counting). Alternatively you can remove, the code from app_timer that stops the clock.

    Once you have a mildly accurate free running counter, you can correlate it to 'real time' with the BLE Current Time Service.

Related