I have an interrupt service routine that's called when a pin on my Arduino Mega is pulled low. It works perfectly for my needs but takes around .15 seconds to run -- I know, an eternity for an ISR, but it works well for me.
The only reason this might be a problem is that I need to be able to buffer incoming hardware serial (UART) data at any time - usually around 10 to 20 bytes per message. I read on another post here (attachInterrupt and serial io - Development - Arduino Forum) that the UART only has a two-byte incoming buffer if the processor is running an ISR, and after that, incoming data is lost. If that is correct, then a lot more than two bytes might arrive while my ISR is running!
PLEASE CONFIRM that the UART is NOT able to fill the 64-byte (or 128 or whatever it is) incoming serial port buffer while the processor is running an ISR.
IF TRUE, my thought is that I could have my ISR check Serial.available and exit the ISR immediately if non-zero. It's no big deal to just skip my ISR because it will get tripped again soon enough. Even if data is coming in the serial port at 115K baud, I am ASSuming that a check for Serial.available() and an immediate return from the ISR will happen even faster than two bytes can arrive. Does this seem reasonable?
Or if there was a clean way to disable interrupts via noInterrupts() when receiving data -- but the timing would seem to be impossible because serial data arrival happens at random times -- and the ISR could be tripped after serial data started to arrive, but before my loop() noticed it with Serial.available().
I can't be the first person to struggle with this, but I've spent two hours searching this forum and Googling to no avail.
The Arduino uses interrupts to take data from the USART and put it in the 64-byte serial input buffer. Interrupts are disabled during an ISR - hence the need to keep each ISR as short as possible. 100 microsecs would be long.
randydpeck:
I have an interrupt service routine that's called when a pin on my Arduino Mega is pulled low. It works perfectly for my needs but takes around .15 seconds to run -- I know, an eternity for an ISR, but it works well for me.
But now you say it doesn't really work at all!
Come on!
You can't have it both ways.
Clearly you need to get rid of the ISR. You need to learn proper coding practice.
Since you haven't really explained anything, this becomes an XY problem.
PLEASE CONFIRM that the UART is NOT able to fill the 64-byte (or 128 or whatever it is) incoming serial port buffer while the processor is running an ISR.
Confirmed - once an ISR is running no other interrupt can take place unless you re-enable the interrupts in the ISR. This means that any data arriving at the UART can not be transferred to the buffer. The UART has one holding register and a hardware shift register which could be seen as two bytes but if the hardware shift register finishes receiving the byte it will over write what is in the holding register and you will loose it. When this happens there is a flag in the UART called "Data over run" that gets set so you can see you have lost data.
It is perfectly valid to re-enable interrupts inside your own ISR. But then you need to write your ISR so that it can't interrupt itself. But, generally, if you are considering doing that you should consider restructuring so that the ISR doesn't take that long.
Grumpy_Mike:
Confirmed - once an ISR is running no other interrupt can take place unless you re-enable the interrupts in the ISR. This means that any data arriving at the UART can not be transferred to the buffer. The UART has one holding register and a hardware shift register which could be seen as two bytes but if the hardware shift register finishes receiving the byte it will over write what is in the holding register and you will loose it. When this happens there is a flag in the UART called "Data over run" that gets set so you can see you have lost data.
Thanks Grumpy_Mike! Regardless of my solution, I will check the "data over run" flag so at least I will know if data was lost. An excellent safety net I was not aware of.
You've confirmed what I was trying to understand, and given me a very helpful tip