How to set up a RTC interrupt?

Hello, I need to accurately increment a counter based on number of seconds since a pin turns on.
I know the NRF_RTC1 exists, and gives us 32768hz accurate clock.
The RTC also supports a “tick” event and interrupt. (See Nordic Semiconductor Infocenter)

Can you explain how to set up the TICK event as an interrupt service routine in Arduino?

Thank you,
Ryan

I think (not an expert of the low level FreeRTOS stuff) the NRF_RTC1 is already used by FreeRTOS and is not accessible to the application.

In 'FreeRTOSConfig.h’
line 37 => // This port of nrf52 use RTC for freeRTOS tick
line 183 => #define xPortSysTickHandler RTC1_IRQHandler

There is as well a comment about it in the Nordic Documentation

Thanks @beegee.

How would I listen for the TICK event in my application code?

As per here, the vector table must be defined by the app in order to support IRQs. This is the area where I’m not sure how to proceed.

For the SoftDevice to locate the application interrupt vectors, the application must define its interrupt vector table at the bottom of the Application Flash Region illustrated in Memory resource map. When the base address of the application code is directly after the top address of the SoftDevice, the code can be developed as a standard ARM® Cortex® -M4 application project with the compiler creating the interrupt vector table.

I tried the code below, per a suggestion from here. It compiles and runs but I get no increments in tick value (i.e. the ISR is not executing). I think the problem here is that I don’t know how to set the ISR function address in the vector table. Arduino doesn’t understand the c++ __interrupt/interrupt keyword in the function definition. Also referenced this slideshow.

Any other suggestions to get an accurately timed ISR? I tried to compare NRF_RTC1->COUNTER in the loop() function then throw a flag to call al ‘1-second function’ but due to other things executing in loop() I get jitter of 200-300+ (a few ms) RTC ticks before the code executes.

Thanks for your advice.

#include <Arduino.h>
#include <LoRaWan-RAK4630.h> //http://librarymanager/All#SX126x (LoRa chipset for RAK4631)

volatile unsigned long tick = 0;

void RTC1_IRQHandler(void)
{
    tick++;
    NRF_RTC1->TASKS_CLEAR = 1;
}

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("Starting up.");
  // put your setup code here, to run once:
  
  NRF_RTC1->EVTEN = (1 << 16);
  NRF_RTC1->EVTENSET = (1 << 16);
  NRF_RTC1->INTENSET = (1 << 16);
  NRF_RTC1->CC[0] = 1;
  NVIC_SetPriority(RTC1_IRQn, 7);
  NVIC_EnableIRQ(RTC1_IRQn);
  NRF_RTC1->TASKS_START = 1;
  __enable_irq();
  Serial.println("NRF RTC tick enabled");
  
}

int i = 0;
void loop() {
  // put your main code here, to run repeatedly:
  if (i > 10000)
  {
    Serial.println("The tick is " + String(tick));
    i = 0;
  }
  i++;
}

Cannot get your code to work either.

Not sure what precision you need, but I was working with xTimer and it seems to by quite precise.
Here an example that creates a timer that is called every 1 tick

#include <Arduino.h>
#include <Adafruit_TinyUSB.h>

volatile unsigned long tick = 0;
volatile bool tick_flag = false;

TimerHandle_t timer_handle;

void my_callback(TimerHandle_t myTimerHandle)
{
	digitalWrite(LED_GREEN, !digitalRead(LED_GREEN));
	tick++;
	tick_flag = true;
}

void setup()
{
	// Initialize the built in LED
	pinMode(LED_GREEN, OUTPUT);
	digitalWrite(LED_GREEN, LOW);

	// Initialize the connection status LED
	pinMode(LED_BLUE, OUTPUT);
	digitalWrite(LED_BLUE, HIGH);
	// Initialize Serial for debug output
	Serial.begin(115200);

	time_t serial_timeout = millis();
	// On nRF52840 the USB serial is not available immediately
	while (!Serial)
	{
		if ((millis() - serial_timeout) < 5000)
		{
			delay(100);
			digitalWrite(LED_GREEN, !digitalRead(LED_GREEN));
			digitalWrite(LED_BLUE, !digitalRead(LED_BLUE));
		}
		else
		{
			break;
		}
	}

	digitalWrite(LED_GREEN, LOW);
	digitalWrite(LED_BLUE, LOW);

	Serial.println("Starting up.");

	// Start timer with time = 1 tick
	timer_handle = xTimerCreate("1_second", 1, true, NULL, my_callback);
	xTimerStart(timer_handle, 0);

	Serial.println("NRF RTC tick enabled");
}

unsigned long last_tick = 0;
void loop()
{
	if (tick_flag)
	{
		tick_flag = false;
		if ((tick - last_tick) == 1000)
		{
			Serial.printf("The tick is %d\n", tick);
			last_tick = tick;
		}
	}
}

Thanks @beegee , I will try xTimer. I was not familiar with that one. I need fairly accurate 1-second ticks as I am monitoring a flow when a pump is running, using the runtime to calculate amount of flow.

Thank you.