Solved: xMega8E5 : My RTC isn't waking up my CPU.

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

I know the RTC is counting by replacing the sleep part with a loop watching for RTC.CNT to change.

 

I know the interrupt is firing by replacing the sleep part with a loop watching for the variable to change.

 

/*
 * ShadeDemo150417.c
 *
 * Created: 4/17/2015 3:18:24 PM
 *  Author: Tom
 */ 


#define F_CPU 2000000

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

#define AdjustPort PORTA
#define LongAdjustPin 4
#define LongPowerPin 3
#define ShortAdjustPin 2
#define ShortPowerPin 1

#define TriggerPort PORTD
#define TriggerClosePin 4
#define TriggerOpenPin 5

void Configure(void)
{
	PORTA.DIR = ~((1<<LongAdjustPin) | (1<<ShortAdjustPin)) ;
	PORTCFG.MPCMASK = ~((1<<LongAdjustPin) | (1<<ShortAdjustPin)) ;
	PORTA.PIN0CTRL = (3<<3) ;
	
	PORTC.DIR = 255 ;
	PORTCFG.MPCMASK = 255 ;
	PORTC.PIN0CTRL = (3<<3) ;
	PORTD.DIR = 255 ;
	PORTCFG.MPCMASK = 255 ;
	PORTD.PIN0CTRL = (3<<3) ;
	PORTA.OUT = 0 ;
	PORTC.OUT = 0 ;
	PORTD.OUT = 0 ;
	
	OSC.XOSCCTRL = (1<<5) ; // Enable 32KHz ULP osc for the RTC
	
	PMIC.CTRL = 7 ; // Enable interrupts in application section without round-robin

}

volatile char IntF = 0 ;

void Delay(uint16_t ms)
{
	RTC.PER = ms ;
	if (ms<4) RTC.PER = 4 ;
	RTC.INTCTRL = 1 ; // Enable int on overflow
	CLK.RTCCTRL = (0<<1) | 1 ; // Enable ULP OSC to RTC
	RTC.CTRL = 1 ; // Divide by 1

    IntF = 0 ;
	sei();
	set_sleep_mode( SLEEP_MODE_PWR_SAVE );
	sleep_enable() ;
	sleep_cpu() ;
	sleep_disable() ;
	RTC.CTRL = 0 ;
	RTC.INTCTRL = 0 ;
	
	
}

ISR(RTC_OVF_vect)
{
	RTC.INTFLAGS = 1 ;
	IntF = 1 ;
}

int main(void)
{
	Configure();
	TriggerPort.OUT = 255 ;
	
    while(1)
    {
        TriggerPort.OUTTGL = (1<<TriggerClosePin) | (1<<TriggerOpenPin) ;
		Delay(1000); 
    }
}

The idea here is to delay with low current draw. My meter says 0.2uA, which indeed is low. My 2000mAH battery should last like 5 million hours which is 584 years. Ok, something will go wrong and the device will be destroyed long before then, so I probably don't HAVE to have that low a current drain :D

The largest known prime number: 282589933-1

In my humble opinion, I'm always right. 

Last Edited: Thu. Apr 23, 2015 - 11:11 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I forgot to wait for syncbusy to clear:

 

 

My delay code now looks like this:

void Delay(uint16_t ms)
{
	RTC.PER = ms ;
	if (ms<4) RTC.PER = 4 ;
	RTC.INTCTRL = 1 ; // Enable int on overflow
	CLK.RTCCTRL = (0<<1) | 1 ; // Enable ULP OSC to RTC
	RTC.CTRL = 1 ; // Divide by 1

    IntF = 0 ;
	while((RTC.STATUS & 1)!=0) ;
	
	sei();
	set_sleep_mode( SLEEP_MODE_PWR_SAVE );
	//set_sleep_mode( SLEEP_MODE_IDLE );
	sleep_enable() ;
	sleep_cpu() ;
	sleep_disable() ;
	RTC.CTRL = 0 ;
	RTC.INTCTRL = 0 ;
	
}

You know, 50 year's battery life would probably be more than adequate

The largest known prime number: 282589933-1

In my humble opinion, I'm always right. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
CLK.RTCCTRL = (0<<1) | 1 ; // Enable ULP OSC to RTC

Are you shifting 0 one bit position to the left?

 

EDIT:  Okay, I guess the result should be good.

Last Edited: Mon. Apr 27, 2015 - 01:33 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The RTC control register has 2 fields: 3 bits to select the clock source and one bit to enable it the RTC. I wanted the code to be clear what I was setting both fields to. I guess I could have put

CLK.RTCCTRL = (0<<1) | (1<<0) ; // Enable ULP OSC to RTC

just to be contrary.

The largest known prime number: 282589933-1

In my humble opinion, I'm always right. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
CLK.RTCCTRL = (0<<1) | 1 ; // Enable ULP OSC to RTC

You are doing this every time through the loop.  Is that necessary?

 

If the interrupt handler runs then the CPU wakes up.

 

If the interrupt handler would increment IntF, then you could see if it runs more than once.

Last Edited: Mon. Apr 27, 2015 - 12:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I use the RTC interrupt to give me periodic interrupts.  I set it up during startup and don't touch it again.  I drive the RTC with the normal 32kHz RC osc., but I guess the ULP osc. should work.

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

Probably don't need to re-enable it each time. Notice that I don't use it for periodic interrupts, but for variable delays.

The largest known prime number: 282589933-1

In my humble opinion, I'm always right.