Can an interrupt interrupt an interrupt?

So I have some code that is reading from a sensor and logging data to the SD card.

Now it might be a bad idea, but I put the writing to the SD card inside the interrupt for simplicity, for the most part this seems to work flawlessly. However, i’m worried that there might be events missed if it is still busy writing when the input changes.

So the question I’m asking here: Is it the case that interrupts, once entered, cannot be interrupted by other interrupts, so that events might be missed?

Also welcome any other pointers. Should I rewrite so that file output is not in the interrupt? My guess here would be to write to some variable to use as a buffer that gets written to SD card on a timer.

I’d opt for a circular buffer - put data into the buffer in your interrupt, and write the data when it’s there.

(I think that interrupts will buffer and be processed in order but I can’t say for sure why I think that :slight_smile: )

Thanks for the reply. It would be great if that were the case that interrupts were stacked and processed in order, but I worry it’s not the case.

I’ve noticed that a few times I’ll get the same edge twice in a row (two rising edges or two falling), which makes me think that It might be missing something, unless this is somehow possible with the hardware. Too much of a noob to figure it out on my own :slight_smile:

If you have any examples of code that does what you describe I’d be grateful for a link.

Circular buffers are easy - just bing it.

In your event handler definition, you have a DateTime value. The value of .ticks will tell you when the interrupt came in, output that with your samples and see what you get.

What is the source of the interrupt? Is it the sensor telling you it’s reached a threshold or a sample is ready?

One thing I would suggest is showing us how you have defined your InterruptPort and Event Handler and any glitch filtering - there are some gotchas that might be coming into play.

in MF interrupts are queued before sending them to your handler. as such, you will not lose an interrupt.

but, if you do not keep up with the interrupts, you will run out of memory.

it is generally good practice to make interrupt processing as fast as possible, and not do io.

It’s pretty simple, set up the pin:


           //PIR Sensor
            InputPort dPIR;
            dPIR = new InterruptPort((Cpu.Pin)FEZ_Pin.Digital.Di34, true, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
            // add an interrupt handler to the pin
            dPIR.OnInterrupt += new NativeEventHandler(dPIR_OnInterrupt);

Then a global variable keeps track and I output the time started and time difference:


static void dPIR_OnInterrupt(uint port, uint state, DateTime time)
        {
            Debug.Print("State:" + state.ToString() + ":" + time.Ticks);
            if (sw != null)
            {
                if (state == 0)
                {
                    //Motion
                    if (pirLastRead == 0)
                    {
                        pirLastRead = time.Ticks;
                    }
                }
                else
                {
                    //No Motion
                    if (pirLastRead != 0)
                    {
                        //prior movement - write interval
                        sw.WriteLine(pirLastRead.ToString() + "\t" + (time.Ticks - pirLastRead).ToString());
                    }
                    pirLastRead = 0;
                }
            }
        }

I’ve monitored the memory used over a short period of time with high activity and it stayed very low. Ran the code for 8 hours and no failure, but with only 1500 writes during that time. I specifically went with streamwriter because I found it to be about 10 times faster than filestream for my useage.

So, if interrupts are queued then this code should be fine. Now my question is why would I get two high/low states in a row? Thankfully this code handles that condition gracefully but it still makes me wonder.

I should also mention that this is a PIR sensor that I wired with a pull up resistor that goes low when motion is detected.

‘sw’ is a global streamwriter that I setup elsewhere, didn’t include code because all of that is working fine.

What does your time interval output show? Exactly the same .Ticks value, or different? If different, then it’s possible it could be “bounce” even though this is meant to be a digital signal (maybe it’s releated to the output voltage of the device; there has to be a threshold where it sees that as a “high” and the ramp may not be leading to a nice sharp edge?)

Hmm, I didn’t think about bounce. But it still shouldn’t bounce UP twice in a row? If it was bounce I’d expect it to bounce both ways? Also it’s very rare, I have to test for quite some time to see it happen, if the signal had noisy edges I would expect to see it quite often.

So looks like what’s actually happening is I’m missing some edges occasionally. I retested last night and missed a falling edge which resulting in a time interval of over 400 seconds, which is simply not possible with the way this PIR sensor (SE-10 from Pololu - Passive Infrared (PIR) Detector SE-10) seems to normally operate. Longest normal ON is usually less than 3 seconds, where as 400 seconds is normal “off” time where I have it situated near my desk.

So it appears for now that interrupts can not interrupt interrupts. I’ll know for sure after I implement a buffer.