PC interrupts ignores events preceding unmask?

It seems that if I unmask pin change interrupts or normal interrupt after an interrupt occurs then this interrupt is discarded
the sequence is

PCICR&=0b11111000;
EIMSK&=0b11000000;

an interrupt concerning these pins occurs

PCICR|=0b00000111;
EIMSK|=0b00111111;

the interrupts is not sevices

Is this the expected behaviour?

Thanks for your time

guy_c:
if I unmask pin change interrupts or normal interrupt after an interrupt occurs then this interrupt is discarded

I don't understand.

It sounds like the interrupt has been serviced because following it you have unmasked something.

And what do you mean by "unmask"? Do you mean prevent or allow future interrupts?

Post a complete program that illustrates the problem - preferably a short program.

...R

Thanks Robin2,
what is meant by "unmasking" is allowing a physical trigger (or simululi or hi to lo xition depending..) to direct the CPU to the corresponding vector and by "masking" is preventing the external trigger to interrupt the cpu from whatever it does.

the simplest case to consider is the following sequence of events

ide pin 3 (mega board) is connected to an external hardware, all other pins are inactive (say open inputs with pullups)

1.- interrupt 5 (at ide pin 3) is masked by EIMASK&=0b11011111
2.- the program runs
3.- an event from the hardware fires interrupts 5 (say by a transition to the correct polarity set in the attachinterrupt)
4.- the program continues uninterrupted.
5.- interrupt 5 is unmasked by EIMASK|=0b00100000
6.- ? what should happen here? shouldn't the cpu go and serve isr of interrupt 5?

It seems to me that it does NOT

My complete program is lengthy so it's easier to discuss the generally expected behaviour

Good question.

What should happen is that when an interrupt pin undergoes it's active transition (rising falling etc, whatever it's configured for in the control register), then the corresponding bit in the corresponding interrupt flag register is set. This should occur even if the global I flag is cleared, and the interrupt remain pending until I flag is set (sti).

I'm not totally sure however if it works the same way if the particular interrupt is masked at the time. There seems to be some inconsistency between exactly how this is described in difference parts of the datasheet.

guy_c:
what is meant by "unmasking" is allowing a physical trigger (or simululi or hi to lo xition depending..) to direct the CPU to the corresponding vector and by "masking" is preventing the external trigger to interrupt the cpu from whatever it does.

the simplest case to consider is the following sequence of events

ide pin 3 (mega board) is connected to an external hardware, all other pins are inactive (say open inputs with pullups)

1.- interrupt 5 (at ide pin 3) is masked by EIMASK&=0b11011111
2.- the program runs
3.- an event from the hardware fires interrupts 5 (say by a transition to the correct polarity set in the attachinterrupt)

It seems to me you have your underwear in a twist.

If (as you say at the top) "masking" prevents an interrupt how can the interrupt happen on line 3 if the interrupt was masked in line 1.

In simple terms an interrupt must be enabled before it can respond to an event.

I think (but I am not certain) that the relevant Interrupt Flag is set when an interrupt event happens regardless of whether an interrupt is enabled. This can have the effect that an interrupt is triggered the instant an interrupt is enabled because something had already set the Flag. Consequently it is usually a good idea to clear the Flags before enabling an interrupt.

...R
PS. Are you sure you are using the correct registers? On an Uno EIMSK only uses bits 1 and 0.

PS. Are you sure you are using the correct registers? On an Uno EIMSK only uses bits 1 and 0.

OP mentioned the mega.

I think (but I am not certain) that the relevant Interrupt Flag is set when an interrupt event happens regardless of whether an interrupt is enabled. This can have the effect that an interrupt is triggered the instant an interrupt is enabled because something had already set the Flag.

And if I understand the description by OP correctly, that is not what is happening. OP expects the interrupt to be serviced. And to my knowledge it should.

OP should post a small example of code that exhibits the behaviour he describes instead of throwing some registers around :wink:

Setting mask bits only defers the interrupt until is it unmasked again. The interrupt bit itself
still gets set by the event in question. You can explicitly clear the interrupt bit to forget
any pending interrupts before unmasking.

The rule is (between any two instructions):
the highest priority unmasked interrupt bit is serviced (assuming global interrupts enabled).

Servicing an interrupt masks global interrupts (on entry), and clears the relevant interrupt bit (on return
I think?). Return from interrupt restores the global interrupt flag too.

MarkT:
Setting mask bits only defers the interrupt until is it unmasked again. The interrupt bit itself
still gets set by the event in question.

This is exactly what I expect. There must be an error in my way of analysing the events - I do logged a trace of the events within the isr(s) which I display in the background code and what I see is that there is a xitions and it is not serviced after unmasking- but I must be making an error somewhere. Ill redo the setup report here.

sterretje:
OP mentioned the mega.

Indeed he did, and I even quoted the relevant line :frowning:

But I still think he is mixed up.

...R

stuart0:
I'm not totally sure however if it works the same way if the particular interrupt is masked at the time. There seems to be some inconsistency between exactly how this is described in difference parts of the datasheet.

I originally replied that masking the interrupts should not stop them from setting the associated interrupt flag, so that the interrupt would remain pending until it was later unmasked. A few minutes later, after looking at the datasheet and seeing what looked like conflicting information on this, I edited my reply as above.

It's an interesting question though and I want to get to the bottom of it. I'm just testing it now and will have all the results in a few minutes.

I just ran a few tests by toggling an interrupt pin and looking at the affect on the interrupt flag register, while the corresponding interrupt was masked. Here are the results.

External Interrupts (INT0 and INT1 on the UNO).

If set for any of the edge sensitive modes, the corresponding interrupt flag is set even when the interrupt is masked.

This means that interrupt events that occur while the interrupt is masked will remain pending until the interrupt is later unmasked.

Pin Change Interrupts (PCINT0 .. PCINT23 on the UNO).

If masked after they're "concentrated" into the three overall interrupt events (in the PCICR resister), then pin change interrupts behave exactly the same as the external interrupts above. That is, they set the corresponding interrupt flag regardless of whether they're masked (in PCICR).

If however they are masked individually in the PCMSK0 .. PCMSK2 registers, then no corresponding interrupt flag is set when the pin change occurs. This means the pin change events that are individually masked (in PCMSKx) will be ignored when that PCINT is later unmasked.

I think that summarizes it pretty well.

BTW. In case anyone was wondering, when the external interrupts are configured as level sensitive then they (when in the active state) don't set a flag in the interrupt flag register. I only observed the flags getting set when the corresponding interrupt pin was configured to be edge sensitive.

I was watching this thread with a growing grimmace on my face until I got to the part where stuart0 demonstrated comprehension of chapter 13 of the datasheet. Thanks!

The various methods of masking interrupts have different behavior - different means of masking are appropriate depending on the desired behavior. .