ATTINY202 - can't get RTC Interrupt to trigger

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Originally, I was using the CMP as sort of a CTC type thing, where I would reset the RTC count inside the ISR. This wouldn't work - the interrupt just never happened. Trying to fix this, I stumbled upon this thread (https://www.avrfreaks.net/forum/...) where it talked about how you can accomplish the same thing the "right" way by setting PER to your desired overflow value (which will do the same thing but will autoclear your RTC count). Now, this is not what I understood the datasheet to say, but you guys know what you're talking about so I switched to that method, which is what I used below. Except, even still, the ISR never triggers from the RTC. I know it's not a problem with the interrupts being disabled, because I have a push button interrupt as well which is working fine. Can anyone help me figure out what I'm doing wrong?

 

(I removed the parts that use the ADC and the external interrupt, but I left the setup parts just in case)

 

#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 312500
#include <util/delay.h>

#define LED PIN2
#define PUMP PIN3
#define RST PIN0
#define TEM ADC_MUXPOS_AIN1_gc
#define RH ADC_MUXPOS_AIN7_gc
#define VDDREF 4

int cycles=0;                             // Not in EEPROM for now
bool needPrime=1;                         // Temporary stand-in for reading eeprom & calculating whether runtime since manual reset is 0

void init(){
  PORTA.DIRCLR = 0xFF;
  PORTA.DIRSET = (1<<LED)|(1<<PUMP);              // PA2 & PA3 as output
  PORTA.OUTSET = (1<<LED);                        // LED off
  PORTA.PIN1CTRL = PORT_ISC_INPUT_DISABLE_gc;     // PA1 & PA7 as ADC inputs
  PORTA.PIN7CTRL = PORT_ISC_INPUT_DISABLE_gc;
  PORTA.PIN0CTRL = PORT_ISC_FALLING_gc;           // Push button interrupt

  CCP = CCP_IOREG_gc;                            // Unlock protected registers for 4 cycles
  CLKCTRL.MCLKCTRLB = 0xB;                       // System clock 312.5 kHz

  VREF.CTRLA = 0x30;
  ADC0.CTRLC = ADC_SAMPCAP_bm | (1 << VDDREF);          // Select sampling cap, 5v ref
  ADC0.CTRLD = ADC_INITDLY_DLY16_gc;                    // ADC sample delay
  ADC0.MUXPOS = ADC_MUXPOS_GND_gc;                      // Sampling GND by default

  RTC.CLKSEL = RTC_CLKSEL_INT32K_gc;                          // RTC low power 32.768kHz source
  while(RTC.STATUS > 0){;}                                    // Ensure startup is finished with RTC
  RTC.CTRLA = RTC_RUNSTDBY_bm | RTC_PRESCALER_DIV32768_gc;    // Run in standby. 1-second resolution allows for 18.2 hr counter
  RTC.PER = 0x1D;                                             // 30 sec timer
  RTC.INTCTRL = RTC_OVF_bm;                                   // Enable overflow interrupt
  RTC.CTRLA |= RTC_RTCEN_bm;                                  // Begin RTC

  sei();
}

int main(void)
{
  init();

  for(;;){

    if(needPrime){
      PORTA.OUTCLR = (1<<LED);              // Turn on LED
      PORTA.OUTSET = (1<<PUMP);             // Run Pump
      _delay_ms(3000);                     // Possible to replace delays with timers & remove delay utility to save space?
      PORTA.OUTCLR = (1<<PUMP);
      PORTA.OUTSET = (1<<LED);
      needPrime = 0;
      cycles = 0;
    }
    if(cycles<19){
      _delay_ms(100);
      PORTA.OUTCLR = (1<<LED);
      _delay_ms(100);
      PORTA.OUTSET = (1<<LED);
    }
    else PORTA.OUTSET = (1<<LED);
  }
}

ISR(RTC_CNT_vect){
  RTC.INTFLAGS = RTC_OVF_bm;              // Clear flag
  cycles++;

    PORTA.OUTCLR = (1<<LED);              // Turn on LED
    PORTA.OUTSET = (1<<PUMP);             // Run Pump
    _delay_ms(2000);                      // Possible to replace delays with timers & remove delay utility to save space?
    PORTA.OUTCLR = (1<<PUMP);
    PORTA.OUTSET = (1<<LED);

}

 

This topic has a solution.
Last Edited: Sat. May 7, 2022 - 01:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Originally, I was using the CMP as sort of a CTC type thing, where I would reset the RTC count inside the ISR.

Why do you need an RTC at all?  Can't you use a timer-are you trying to do something at a specific time (like turn on LED at 11:37:20 AM on Wed 3/15/2027)? 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In theory, yes. However, my understanding is that this isn't a true RTC anyway, it's a pseudo RTC, and it can't do that. But it has other desirable qualities, like running off a separate low-power clock source, running on standby, etc. It's not my project I'm just helping write some test firmware for it (a timescaled version of what it will be fleshed into later, so they can use it to empirically derive some other values). Ultimately, the answer is, the project owner wants it done with RTC. 

Last Edited: Fri. May 6, 2022 - 10:02 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need to check for synchronization busy before every write to registers on the RTC clock domain. Either your period isn't getting set or the final enable isn't going through.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Thank you, this fixed it!