XMEGA Interrupt (INT0 vs INT1 oddity..) [SOLVED]

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

Hi, Folks.

UPDATE - SOLVED.

Sorry for bothering, I fixed it. However, this may as well stay as a kinda "gotcha!" warning.

Highlit in red is my mistake. Somehow, I thought INT1LVL and INT0LVL were in different registers. They're not so needed |= (or-equal) not just equal.

I'm tearing my hair out with something with interrupts that should be straightforward. Device is Xmega256A3U

Basically I have two pins on port D, pins 0 and 1. I've set them up as below to use int0 and int1 vectors, respectively.

Problem is, if I comment out all the lines for Pin 1( as below) Pin0 interrupt works. But if I re-enable the commented lines, Pin0 interrupt doesn't work, only Pin1 does...

(Tool is AS6.2, Atmel ICE Basic). Single-step/judicious use of breakpoints/examining peripheral registers sheds no light - it seems correct...

Any help for this novice would be greatly appreciated!

-Thanks

-Andy

 

Relevant snippets below:

First, the port pins themselves:

		// Special case for pin 0 - it's used for Counter_0
	PORTD_PIN0CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_RISING_gc;		// Rising, to help debounce
	PORTD_INT0MASK = PIN0_bm;
	PORTD_INTCTRL |= PORT_INT0LVL_MED_gc;
		//// And Pin 1, for counter_1
	//PORTD_PIN1CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_RISING_gc;		// Rising, to help debounce
	//PORTD_INT1MASK = PIN1_bm;
	//PORTD_INTCTRL |= PORT_INT1LVL_MED_gc;

PMIC setup:

PMIC_CTRL = PMIC_MEDLVLEN_bm;			// Medium level interrupts for counters and 1 min. clock
sei();

And finally, the ISR's themselves: (The PortD pin 6 mularkey is so I can measure the ISR duration on a logic analyser)

ISR(PORTD_INT0_vect)
{
	PORTD.DIR = PIN6_bm;
	PORTD.OUTSET = PIN6_bm;
	uint8_t temp = SREG;	// preserve status register
	delay_selector();			// Delay according to actual system clock speed. Ideally, a 1ms delay...
	counter_0 += 1;
	SREG = temp;
	PORTD.OUTCLR = PIN6_bm;
}

ISR(PORTD_INT1_vect)
{
	PORTD.DIR = PIN6_bm;
	PORTD.OUTSET = PIN6_bm;
	uint8_t temp = SREG;	// preserve status register
	delay_selector();			// Delay according to actual system clock speed. Ideally, a 1ms delay...
	counter_1 += 1;
	SREG = temp;
	PORTD.OUTCLR = PIN6_bm;
}

 

Last Edited: Sat. Feb 13, 2016 - 07:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

At least you are overwriting the INTCTRL. You should have:

 

PORTD_INTCTRL = PORT_INT0LVL_MED_gc | PORT_INT1LVL_MED_gc;

 

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

Yeah, I spotted it about the same time you posted....Somehow, without my manual to hand, I stupidly thought the two INTLVL things were in different registers.
What a chump! Goes in my "I learned about code from that!" folder...

(I know your code is shorter, but I'm from the "Blunt Force Trauma school of programming". Easier for me to look at it later and figure it out. Hell, reckon the optimizer'll take care of it... )

Thanks!

-Andy, Oulu, Finland.

 

Last Edited: Sat. Feb 13, 2016 - 07:40 PM