I needed to learn how to do interrupt handling on the Nordic. The simplest thing seemed to be to setup the RTC to generate regular interrupts. It was a useful process because I learned quite a bit about the hardware in the process.
(My test program is called: RTC_C_nRF51822)
There are two clocks: a low-frequency clock, and a high-frequency clock. The LFCLK runs at 32KHz. It generates the basic system tick which is a sub-multiple of the 32768Hz. The PRESCALAR which essentially divides the clock is only 12 bits wide, so the slowest clock-tick is 32768/(0xFFF + 1) = 8Hz.
#define RTC_FREQUENCY_HZ (10UL)
#define COUNTER_PRESCALER ((LFCLK_FREQUENCY / RTC_FREQUENCY_HZ) – 1)
The name of the interrupt routine is hard-wired : void RTC0_IRQHandler() It gets called at RTC_FREQUENCY_HZ.
There is another times called the “compare” timer that can be set to cause an timer interrupt at any multiple of RTC_FREQUENCY_HZ.
Whereas the basic tick interrupt repeats automatically, the compare timer is a one-shot and has to be restarted.
So the basic process involves setting up the timer frequencies, and the interrupt events and masks, and then going to sleep until a tick, or “compare” interrupt occurs.
The sleep loop is a little subtle. It is important to make sure that all pending interrupts are processed before sleeping, for which this opaque/confusing sequence is recommended.
// Enter System ON sleep mode __WFE(); // Make sure any pending events are cleared __SEV(); __WFE();
Incidentally I learned that the basic printf procedure is interrupts driven, so it get’s a bit confusing.
So here’s an example that toggles one LED every ten system ticks, and the other at 3Hz.
I noticed that in sleep mode the board is still consuming about 1.5mA with the LEDs off.