Configuring EICR after sei() changes the behavior

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

I was working on external interrupt. The code below works fine and LED toggles at the rate of 3000 msec ON time and 500 msec OFF time. But if 

EICRA|=((1<<ISC00)|(1<<ISC01));

is placed after sei(), I see 3000msec offtime and 500msec on time. How this sequence affect the toggle operation even after adding 10msec delay before entering while loop? I can see that LED flashes once before entering while loop in this case. That means does configuring EICRA register causes any interrupt?

 

ISR (INT0_vect)

{

    PORTD^=(1<<PD3);   // Toggle the port pin

}

 

int main(void)

{

 

    DDRD|=((1<<PD3)|(1<<PD4));

    PORTD &= ~((1<<PD3)|(1<<PD4));

    PORTD|=1<<PD2;  // Enables pull up

    EIMSK |=1<<INT0;

    EICRA|=((1<<ISC00)|(1<<ISC01));

    sei();

   // Behavior changes if EICRA initialization is moved to here

   //EICRA|=((1<<ISC00)|(1<<ISC01));

    _delay_ms(10);

    while(1)

    {

        PORTD|=1<<PD4;

        _delay_ms(3000);

        PORTD&=~(1<<PD4);

        //_delay_us(1);

        PORTD|=1<<PD4;

        _delay_ms(500);

        PORTD&=~(1<<PD4);

        //_delay_us(1);  // Added delay. Had some issues on few occasion.

    }

}

 

Note: For some reason, add code <> is not working today for me. Nothing happens when <> is clicked. So could not place the code inside <>. Sorry for the inconvenience.

Last Edited: Sun. Apr 15, 2018 - 05:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You should always configure ALL registers before the sei() and if there's a chance any of the IF flags being set you probably want to clear those (write 1 bits) before the SEI

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

 if there's a chance any of the IF flags being set

After reset, initial values of EIFR register is supposed to be 0. How these flags could get set then? Anything might get set in start up code or in boot loader? I am using cheap nano board (CH340 based).

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

As soon as you have configured an interrupt source it's possible the events may trigger. Consider for example a timer set to run fast with a compare register set to 0x0001. That event may occur within a cycle or two from starting the timer even before you get to the SEI. so an OCIE1 or something will get set. When you SEI the CPU will execute just one more opcode then on the next instruction fetch it will see the flag and jump to the vector. The point being that the condition that triggers the interrupt may have occurred and be latched even before the interrupting system is turned on.

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

Agreed for timer interrupts etc. But in my case, PD4 was pulled low and PD4 was connected to PD2 (Sorry, I did not indicate this in my description, but I guess you understood that already) and hence the input is in stable low state before enabling ISR. I feel it should not have triggered the ISR. 

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

As you say I can't know you circuit but maybe noisy signals or something?

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

joneewheelock wrote:
How these flags could get set then?

Remember that the flag register(s) can be set whenever the condition is true.  Isn't EICR of 0 a valid value?

 

[edit]  No AVR model given.  Title and post say "EICR".  But code says EICRA which makes sense for Mega88 family.

 

So what does the datasheet say about EICRA? 00 is valid for low level.  So could the INT0 pin or the INT1 pin be read as a low level?  I don't see why not.  If read as low level, then why does the associated flag bit being set surprise you?  I'm thinking "sour grapes"  -- if a result isn't exactly what you expect or desire, then there muse be something wrong with the causality.

 

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.

Last Edited: Sat. Apr 14, 2018 - 09:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Device tag was added as ATMEGA328P and that is why I did not specify in the description.

 

OK, I think I got the problem. Default value of EICRA=0. That means The low level of INT0 generates an interrupt request by default. So as soon as INT0 in EIMSK is set and I bit is set, spurious interrupts will be generated right away before EICRA is configured in next line (since PD4 is set to LOW which is connected to PD2).

 

But I am getting another doubt here. In the situation when INT0 pin is low and interrupt is configured for low level, continuous INT0 interrupts might occur and main() should not get any chance to run right? How processor will handle such situation? Does it execute some code in main loop also?

Last Edited: Sun. Apr 15, 2018 - 11:47 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After RETI the AVR always executes one opcode before doing the next interrupt vector. So even if it's flooded with interrupts the stuff in main() will, very slowly, execute.

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

joneewheelock wrote:
So as soon as INT0 in EIMSK is set and I bit is set, spurious interrupts will be generated right away before EICRA is configured in next line (since PD4 is set to LOW which is connected to PD2).

Well, almost.  As I mentioned, the bit(s) in the flag register can/will be set regardless of whether you fuss with the mask register or not.  So the bit is set >>before<< you start setting up for the interrupt.

 

It is a classic race, with a well-known sequence to avoid any races.

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.