[SOLVED] Possible to use internal real-time counter from Arduino Nano Every?

Hello everyone,

Recently I've been wanting to use the real-time counter (RTC) onboard the Arduino Nano Every, specifically the OSCULP32K oscillator in periodic interrupt (PIT) mode. Afaik there aren't any libraries to do this , so I wrote some code to manually set the registers as described in the ATMega4809 manual (page 263):

#include<avr/io.h>
#include<avr/interrupt.h>

volatile bool test = 1;

ISR(PIT_vect) {

  test = 0;

  noInterrupts();
  
}

void setupInterrupts() {

  //To operate the PIT, follow these steps:
  //1. Configure the RTC clock CLK_RTC as described in   Configure the Clock CLK_RTC.

  RTC.CLKSEL = 0x00; //Use OSCULP32K oscillator
    
  //2. Enable the interrupt by writing a '1' to the Periodic Interrupt bit (PI) in the PIT Interrupt Control
  //register (RTC.PITINTCTRL).

  while (1 & RTC.PITSTATUS); //check if register isn't busy
  
  RTC.PITINTCTRL = 0x01; //Enable interrupts
  
  //3. Select the period for the interrupt and enable the PIT by writing the desired value to the PERIOD bit
  //field and a '1' to the PIT Enable bit (PITEN) in the PIT Control A register (RTC.PITCTRLA).

  while (1 & RTC.STATUS); //check if register isn't busy

  RTC.PITCTRLA = 0x31; //This should set the clock to trigger an interrupt every 128 clock cycles (The clock frequency is 32768Hz, so every 1/256 seconds)

  return;
  
}

void setup() {

  Serial.begin(9600);

  setupInterrupts();

  while(test);

  Serial.println("Interrupt triggered!");
  
}

void loop();

The serial output I get is:

so that's not very motivating.

Maybe the RTC is already being used by the Arduino board itself?

If anyone knows more about this or whether this is possible at all, I'd greatly appreciate it!

I'm pretty confident official core isn't touching the RTC.

But what are you doing setting noInterrupts() in the ISR?! Don't do that!

If you want to disable that interrupt, disable that specific one - don't try to mess with the global interrupt settings (not even sure what that would even do, but you definitely shouldn't be doing that there).

Also, I don't know if the official core has the fix for Serial working correctly right after it was set up... There was a bug in early versions of megaavr cores where the setup was done wrong and the first few characters were mangled if you tried to send them right after initializing serial... I would council use of MegaCoreX rather than the official megaavr core for even official megaavr boards.

DrAzzy:
I'm pretty confident official core isn't touching the RTC.

But what are you doing setting noInterrupts() in the ISR?! Don't do that!

If you want to disable that interrupt, disable that specific one - don't try to mess with the global interrupt settings (not even sure what that would even do, but you definitely shouldn't be doing that there).

Also, I don't know if the official core has the fix for Serial working correctly right after it was set up... There was a bug in early versions of megaavr cores where the setup was done wrong and the first few characters were mangled if you tried to send them right after initializing serial... I would council use of MegaCoreX rather than the official megaavr core for even official megaavr boards.

Hmm weird, I usually never have any issues with the serial connection. I don't know why it would send me this at all, because if I remove the println(), it still sends the same gibberish.

ISR(PIT_vect) {

Needs to be:

ISR(RTC_PIT_vect) {

And you need to explicitly clear the intertupt souce:

ISR(RTC_PIT_vect) {
  test = 0;
  RTC.PITINTFLAGS = 1; // reset interrupt
}

Good catch!

Yeah, that would explain why it doesn;t work - one of the incredibly perverse things about the compiler is that ISR() with a bogus vector isn't a compile error -

What will happen is the ISR will fire, and there's no ISR defined, so it goes to the bad vector handler (which just jumps to 0x0000 - but since the interupt flag never gets cleared, as soon as it reenables interrupts, it will just fire again....

westfw:
Needs to be:

ISR(RTC_PIT_vect) {

And you need to explicitly clear the intertupt souce:

ISR(RTC_PIT_vect) {

test = 0;
  RTC.PITINTFLAGS = 1; // reset interrupt
}

This solved it for me, thank you guys so much for your time and knowledge!