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

  • I like the idea of mixing a RTC timer and a counter to get seconds and ticks. Especially if can be done both low power and without an interrupt. But it is not clear how you would do this while sharing the RTC with app_timer. On the nrf52 you have an extra RTC to use, but on the nrf51 only the one RTC is available for app use and it is used by app timer.

    Using a spare timer to count RTC overflows seems pretty straight forward, I'll have to switch over to that. The race window on incrementing my overflow count is a quite a bit bigger then I originally thought. I was only thinking of it when the timer is read from the main app and not thinking that I mostly read it from other interrupt handlers. I really wish the nrf51 had more priority levels available to to the application when using the softdevice. Luckily the nrf52 adds more priority levels which will be useful for stuff like this.

  • My idea is to connect one of the RTC1 COMPARE events with the TIMER1 COUNT task using PPI. In my opinion (I am not sure it is possible) this is a just a configuration of RTC1: RTC1 will continue to produce TICK events which are used by the app_timer library but it will also produce COMPARE events (configured to happen every second) which will increment the counter on TIMER1 directly, without software intervention. As you said before, one thing to consider is that app_timer stops the RTC1 when not needed, so, as you suggested, it is possible to remove that code or keep a timer always pending. Another thing I noticed looking briefly at the app_timer code is that the RTC1_IRQHandler clears all the events, including the COMPARE, this probably should be removed as well.

  • Hi Alessandro, did you ever get this working? I have a very similar need. I need the app_timer subsystem, but I also want to use compare events to keep a 1 second count in the TIMER1 COUNT. The one thing I haven't figured out is how to update the RTC1 CC register I need without generating a RTC1 interrupt. My prescaler is set to 0 for the RTC, so the counter will not overflow for 512 seconds. So, I either need to increment my CC register in the RTC1 interrupt which I am trying to avoid, or I guess I could change the MAX_RTC_COUNTER_VAL to 0x0000FFFF so that it only has a one second period. Any thoughts?

  • Hi John, I didn't implement it yet, I might try over the weekend. I think I missed an important problem, the fact that the RTC counter will continue to count and after the first COMPARE event it will be greater than the CC register. In this situation, the next COMPARE event will be triggered only after the RTC will overflow and start again from zero. The first idea that comes to my mind is to use the COMPARE event to trigger the COUNT on TIMER1 and the CLEAR on the RTC using PPI. This should be possible as written on the reference manual, but I don't know if it is a problem for the app_timer module.

    It is also not very clear to me how the app_timer uses the COMPARE[0] event.

  • Hi Alessandro, that is exactly the problem I have run into with this. The app_time system is merely pushing the COMPARE[0] register out as far as it needs to to trigger the next timer(s) as I read the code. I am attempting to set the MAX_TRC_COUNTER_VAL to 0x0000FFFF so that the app_timer system uses RTC1 as a 16-bit timer rather than 24. I'll let you know how that goes. Eventually I'd like to move to the nRF52, but RTC2 is listed as not working in the initial PAN so that has to wait for the next chip revision.

Related