Electronic – What’s the maximum time an interrupt service routine can take to execute on ATmega328P

atmegaatmega328pavrmicrocontroller

I have an ATmega328P that checks if a button was pressed via pin change interrupts. Now, I want to turn on an LED for 200 ms.
Can I just turn the LED on, wait 200 ms and turn it back off in the ISR like in the following code?

ISR(PCINT1_vect)
{
    if(PINB & 0b1)
    {
         PORT = 0b10;
         _delay_ms(200);
         PORT = 0;
    }
}

In a few forum posts on AVR Freaks, I've read that you shouldn't spend much time in an ISR, but I've never seen any exact numbers. I sadly can't find those posts anymore, so I can't link them. As far as I can remember, they all said, that if you spent to much time in the ISR, the microcontroller might crash.
Is that true? And if so, is there an exact time limit after that this might happen?

Best Answer

If nothing else is running in the MCU, then you are free to take as long as you like in the ISR. But, this is a bad habit to get into, and it means that if you want to do anything else, you'll likely have to rework the code.

A particular case is if the MCU is using a serial library, that expects interrupts to be working often enough to service individual characters received. At 115,200 baud (a high serial speed often used to minimise download time), there is less than 100 µs between characters. If you block the interrupts for longer than that, you risk losing input characters.

As a general rule, do the absolute minimum in an ISR. In your application, a reasonable design would be to have an interrupt every ms, which increments and checks a counter value. I'm sure you can work out some suitable logic to set and test the counter to get 200 ms between turn on and turn off events.