strange xmega port interrupt behaviour?

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

I have two inputs on PORTF that are configured to generate interrupt 0 and interrupt 1 on rising edge. It seems that interrupt 0 can also trigger interrupt 1. I tried all kinds of things, but my current work-around is to check the actual pin level upon entering interrupt handler and abort if the pin isn't high.

Anybody else see anything similar or have a suggestion?

init code:

PORTCFG.MPCMASK = 0x00;
PORTF.INTCTRL = 0x0f;
PORTF.INT0MASK = 0x01;
PORTF.INT1MASK = 0x02;
PORTF.PIN0CTRL = 0x99;
PORTF.PIN1CTRL = 0x99;
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It looks about like the AVR1313 app note (I'm not an Xmega user yet).

There seems to be a bug at first glance, very similar to one I found in the Virtual Ports app note unless I'm missing something:

void PORT_ConfigureInterrupt0( PORT_t * port,
                               PORT_INT0LVL_t intLevel,
                               uint8_t pinMask )
{
	port->INTCTRL = ( port->INTCTRL & ~PORT_INT0LVL_gm ) | intLevel;
	port->INT0MASK = pinMask;
}


/*! \brief Configures interrupt 1.
 *
 *  This function configures interrupt 1 to be associated with a set of pins and
 *  sets the desired interrupt level.
 *
 *  \param port       The port to configure.
 *  \param intLevel   The desired interrupt level for port interrupt 1.
 *  \param pinMask    A mask that selects the pins to associate with port interrupt 1.
 */
void PORT_ConfigureInterrupt1( PORT_t * port,
                               PORT_INT1LVL_t intLevel,
                               uint8_t pinMask )
{
	port->INTCTRL = ( port->INTCTRL & ~PORT_INT1LVL_gm ) | intLevel;
	port->INT1MASK = pinMask;
}

INTCTRL has a mask applied for the particular interrupt (0/1), but then just OR's intLevel in both 0 and 1 cases without any shifting or masking.

Nothing jumps out at me that you are doing something effectively quite different than the app note code.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

This is what I'd try:

Remove PORTCFG.MPCMASK = 0x00;

PORTF.INTCTRL = 0x0f;

Are your ports really at the high IRQ level, with PMIC set accordingly? Does it work if you just use the default low level?

PORTF.PIN0CTRL = 0x99;
PORTF.PIN1CTRL = 0x99;

0x99 gives a slew rate limited rising edge with pull up enabled. Having slew rate limiting set on an input seems rather odd?

Using symbolic names would make your code a lot clear:

PORTF.PIN0CTRL = (PORT_SRLEN_BM|PORT_OPC_PULLUP_gc|PORT_ISC_RISING_gc);

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

theusch wrote:

INTCTRL has a mask applied for the particular interrupt (0/1), but then just OR's intLevel in both 0 and 1 cases without any shifting or masking.

Lee

The shif is in the defintion:

/* Port Interrupt 0 Level */
typedef enum PORT_INT0LVL_enum
{
    PORT_INT0LVL_OFF_gc = (0x00<<0),  /* Interrupt Disabled */
    PORT_INT0LVL_LO_gc = (0x01<<0),  /* Low Level */
    PORT_INT0LVL_MED_gc = (0x02<<0),  /* Medium Level */
    PORT_INT0LVL_HI_gc = (0x03<<0),  /* High Level */
} PORT_INT0LVL_t;

/* Port Interrupt 1 Level */
typedef enum PORT_INT1LVL_enum
{
    PORT_INT1LVL_OFF_gc = (0x00<<2),  /* Interrupt Disabled */
    PORT_INT1LVL_LO_gc = (0x01<<2),  /* Low Level */
    PORT_INT1LVL_MED_gc = (0x02<<2),  /* Medium Level */
    PORT_INT1LVL_HI_gc = (0x03<<2),  /* High Level */
} PORT_INT1LVL_t;

ie:

PORT_ConfigureInterrupt1( &PORTF, INT1LVL_HI_gc, 0x01 );
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

There seems to be a bug at first glance, very similar to one I found in the Virtual Ports app note unless I'm missing something:

I don't see a bug in the app note. Looks like it just masks off the level that you are currently changing using the _gm (group mask) and then applies the new interrupt level. (the bit shifting is done in the header file).

I tried using the app note code at first, but then set everything directly just in case..

I don't see any difference in behaviour either way.

[edit]
I should mention that after interrupt 0 appears to trigger interrupt 1, it doesn't trigger it again until some period of time passes? I'm looking at this on a scope and I don't see any level change on int0, but when int1 changes, it triggers int0 handler as well as int1. I have also tried making the interrupt levels different for int0 and int1 and see no difference with regard to the behaviour I'm describing.

I'm sure it is something I'm doing wrong, but not sure what yet. For this application, the work-around I'm using is fine.

Last Edited: Fri. Jul 24, 2009 - 07:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bpaddock wrote:
This is what I'd try:

Remove PORTCFG.MPCMASK = 0x00;

PORTF.INTCTRL = 0x0f;

Are your ports really at the high IRQ level, with PMIC set accordingly? Does it work if you just use the default low level?

PORTF.PIN0CTRL = 0x99;
PORTF.PIN1CTRL = 0x99;

0x99 gives a slew rate limited rising edge with pull up enabled. Having slew rate limiting set on an input seems rather odd?

Using symbolic names would make your code a lot clear:

PORTF.PIN0CTRL = (PORT_SRLEN_BM|PORT_OPC_PULLUP_gc|PORT_ISC_RISING_gc);

Bob,
Thanks for the suggestions. I started off without clearing the MPCMASK and added it just to see if it made a difference. Same thing with slew rate, I meant to clear that before posting, but didn't.

I definitely agree with your comment about readability too. I'm just trying to figure out the problem right now.

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

Quote:

then applies the new interrupt level

Oh, I see it now--a fancy enum. Yah know, I was always trying to figure out how to ensure that e.g. TOIE1 was always applied to the right TIMSK register. This is a step in the right direction, but one could still "lie".

"Never mind" -- Emily Litella (Saturday Night Live character)

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

bpaddock wrote:

Are your ports really at the high IRQ level, with PMIC set accordingly? Does it work if you just use the default low level?

Bob,
That works correctly. I had tried different levels for each, but not both low. I clearly need to read more about how the PMIC works.

Thanks

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

Oops... spoke too soon. (I had set both interrupts off, not low). I'm still seeing the same problem with all interrupts set to low level and PMIC configured to only allow low-level interrupts.

I'll keep working at it.