Real-time counter stale values

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

I am using the atxmega64a3u. I put it into sleep mode (POWER_SAVE) in which 4 sources can wake it up:
1) asynchronous IO interrupt on port a
2) asynchronous IO interrupt on port b
3) RTC compare match
4) RTC overflow
My RTC is connected to a 32.768kHz crystal with a prescalar of 8 resulting in a 4.096kHz clock. My main clock is using the internal oscillator (calibration bits set for 48MHz) with a prescalar of 2 for my system clock.

In the code for my asynchronous interrupt handler below you'll see that I grab the RTC counter values twice. I would've thought the second time unnecessary (at most the RTC counter values would be off by a fraction of a second), but I find that the second values are different from the first values by more than 4096 counts (1 second, sometimes more than 3 seconds).

Is there some kind of time spec on when registers can be read (like RTC counter) after waking up? The system clock should be stable before it starts executing code, right?

ISR(PORTA_INT0_vect)
{
	volatile uint8_t eventTSHold[7];
	int16_t currEventEELoc;
	
	eventTSHold[5] = RTC.CNTL;
	eventTSHold[4] = RTC.CNTH;
	eventTSHold[3] = ucRTC[0] & 0xFF;
	eventTSHold[2] = (ucRTC[0] >> 8) & 0xFF;
	eventTSHold[1] = ucRTC[1] & 0xFF;
	eventTSHold[0] = (ucRTC[1] >> 8) & 0xFF;
	eventTSHold[6] = 2;	// pushbutton 2
	//mdelay(20); debounce time is effectively write time of eeprom
	nvm_eeprom_erase_and_write_buffer((eeprom_addr_t)SAVEPKTTSEELOC, (const void*)eventTSHold, TSLEN);
	if (ioport_pin_is_high(GPIO_PUSH_BUTTON_2)) return;	// debounce
	// record event, but only if less than 100 or fewer events
	currEventEELoc = nvm_eeprom_read_byte(EVCAPEELOCPH) << 8;
	currEventEELoc += nvm_eeprom_read_byte(EVCAPEELOCPL);
	if (currEventEELoc > EVCAPEELOCED) return;
	ioport_set_pin_low(LED4_GPIO);
	eventTSHold[5] = RTC.CNTL;
	eventTSHold[4] = RTC.CNTH;
	eventTSHold[3] = ucRTC[0] & 0xFF;
	eventTSHold[2] = (ucRTC[0] >> 8) & 0xFF;
	eventTSHold[1] = ucRTC[1] & 0xFF;
	eventTSHold[0] = (ucRTC[1] >> 8) & 0xFF;	
	nvm_eeprom_erase_and_write_buffer((eeprom_addr_t) currEventEELoc, (const void*)eventTSHold, TSLEN+1);
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

but I find that the second values are different from the first values by more than 4096 counts

Surely that's just the time that:

nvm_eeprom_erase_and_write_buffer((eeprom_addr_t)SAVEPKTTSEELOC, (const void*)eventTSHold, TSLEN); 

takes to execute? EEPROM writing is one of the slowest things you can do on an AVR.

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

Can't be that long. 4096 is 1second on that counter. Datasheet for the atxmega64a3u states 12ms for EEPROM page erase&write. I am doing writing 7 bytes so worst case is 86ms.

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

Run a timer either side of the call to confirm timing.