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

Advertising causes timer1 delay?

My project: nRF51422, S110, based on SDK 7.1.

My project employs several application timers (run via the scheduler) and a continuously running Timer1-based 1ms timestamp counter. Timer1 increments a static counter variable on each CC0 interrupt. An application (scheduled) timer runs a battery check every 5 seconds (for BAS service). The system appears to run fine while advertising as long as a potential client (not connected) is NOT activated in the vicinity. As soon as a potential client (again, not connected) is switched on (iPhone /iOS8.1, running "LightBlue" app) Timer1 looses over 1 second between the 5 second battery check intervals. In the Segger RTT captures below each battery reading is preceded by the (Timer1 based) 1ms timestamp, followed by the time since the last reading. The "LightBlue" app is activated at timestamp [66017].

image description

If the client connects, the timer once again becomes accurate.

image description

Upon disconnection, the timer once again looses time.

image description

I have Timer1 set for HIGH interrupt priority. Is this expected? Any idea why this is happening?

Update: Altering the timer to interrupt at 10ms, instead of 1ms, intervals appears to remedy the issue. Apparently the processor can't keep up with all the interrupts while the soft device is working on advertising.

  • Hi

    I think your assumption is correct. The peripheral will send an advertising packet, then start the RX receiver in order to listen for a potential connection request or scan request. If the central device is an active scanner (i.e. sends a scan request) the peripheral will respond with a scan response packet, which will increase the blocking time of the CPU.

    IOS generally performs active scanning when the IOS app is in the foreground, which explains the behavior. When the peripheral is advertising and does not send scan response packet, I suspect the CPU is blocked for less than 1 ms, but when sending scan response packet the CPU is blocked for more than 1 ms.

    If the CPU is blocked during two consecutive Timer1 interrupts, you will lose one interrupt, i.e. for two timer1 interrupts, the counter will only be incremented once.


    I suspect the problem can be solved by using third revision nRF51 hardware and softdevice 110 7.1+ which allows for the CPU to be used during radio activity. See this thread how to unblock the CPU for S110 v7.1.0 (only works with third revision nRF51, see comp matrix for what nRF51 devices are third revision). For S110 v8.0.0, the CPU is unblocked by default.

    If you look at the S110_softdevice Specification version 1.3 (targeted at softdevice 7.0.0), section 11.3.1, you see that the softdevice can block the CPU up to 1700 us. If you however look at the same section in S110_softdevice Specification version 2.0 (targeted at softdevice 8.0.0), you see the CPU blocking time during advertising is only 440 us.

    An idea of a workaround is to use Timer1 with 1ms interrupt frequency and use Timer2 as counter, and let Timer1 CC0 event trigger a counter task on Timer2 trough a PPI channel. That way, no CPU is needed to increment the ms counter.

    Another dirty workaround would be to advertise with whitelist. The peripheral will not send scan response packet to a central that is not in the whitelist.

  • Thanks for your response. I attempted to update my project to 8.0 a while ago, but ran into a number of issues and had to back off. The changes were difficult to reconcile and frequently undocumented. Updating to 8.0 is probably the best ultimate best solution, so I plan to try once again. For now 10ms of resolution works well enough for this project to move forward.

  • To decrease the CPU blocking time, you do not need SDK 8.0.0/8.1.0 + S110 8.0.0. You can continue using SDK 7.1.0 and S110 7.1.0 and unblock the CPU in order to have maximum latency less than 1ms during advertising. But again, unblocking the CPU will only work if you have third revision nRF51.

  • I use the old SDK 5.2.0 and S110 6.0.0; I use the app timer to count sec,min,hour(make one time clock), and found that the second of mine is less after i set an initial sec/min/hour and run for some days. how to avoid delay the app timer of old SDK?

  • @hawk The app timer uses RTC1 in the background which in turns uses 32kHz clock source. What clock source are you using? The app_timer drift can be caused by the drift of the clock source chosen.

    How to choose a clock source: When you initialize and enable the softdevice by calling ble_stack_init, you have several clock source options which either use external 32kHz crystal or internal 32kHz RC oscillator. If you use the RC, the accuracy is 250ppm, when you use crystal, it usually has better accuracy.

Related