Nested interrupts using NOBLOCK

Hello Forum,

I am running a code that interrupts every 1ms using TIMER2 overflow. I programmed the ISR for the TIMER2 as NOBLOCK hence nested interrupts are enabled. This ISR checks for bytes available to read on serian receive buffer and processes them.

What will happen if somehow I receive a byte on my serial Hardware port during my TIMER2 ISR? Will the Rx ISR interrupt my current TIMER2 ISR and insert that byte onto the serial receive bufer or will it just set the flag and wait until TIMER2 ISR is over and then process that incoming byte?

I am not clear if there is a interrupt priority when using nested interrupts or not.

Just to be on the safe side, I disable TIMER2 interrupts during TIMER2 ISR.

Thank you very much for your help.

tero2011:
I programmed the ISR for the TIMER2 as NOBLOCK...

Why?

Because I receive bytes thru serial port that I cannot miss. If ISR is NOBLOCK there are chances that I lose bytes if more than one arrive during my ISR, right?

Thanks.

tero2011:
Because I receive bytes thru serial port that I cannot miss.

That is not a valid reason to do what you are doing. There is almost never a valid reason to use nested interrupts.

If ISR is NOBLOCK there are chances that I lose bytes if more than one arrive during my ISR, right?

My crystal ball is broken. So, without source code, I have no idea how your program will behave.

Forgot to mention that I am using Arduino Mega2560 and I also use Hardwareserial library.
I am on my Cel phone and cannot paste code right now.

Hardwareserial uses interrupts to process incoming bytes and fill its internal library buffer, so I thought that to be 100% sure I do not miss any incoming byte during my ISR I better use nested interrupts.
When entering ISR I disable timer2 interrupt to avoid looping.

All this is due to the fact that I have to use malloc() inside my ISR (not in all cases of my ISR) which I know can delay the execution.

Thanks

tero2011:
All this is due to the fact that I have to use malloc() inside my ISR (not in all cases of my ISR) which I know can delay the execution.

Delay execution? Maybe. Fatal flaw? Absolutely. The AVR-Libc malloc is not safe to use from an interrupt service routine.

I disable temporarely global interrupts before performing malloc() and re-enable them right after. Si no fatal flaw there I think.

Thanks

I have a simple philosophy.

Don't use interrupts unless you know enough about what you are doing not to need to ask questions here.

Ditto for nested interrupts.

Ditto for complicated memory management on a very small device.

...R

Robin2:
Don't use interrupts unless you know enough about what you are doing not to need to ask questions here.

Love it!

We haven't see any code yet and also don't know what you are trying to achieve, but it's pretty hard to think of a good reason to use "malloc" and "nested interrupts" in the same sentence.

Can you explain what you are trying to achieve, not how you think it should be done.


Rob

I initially started this thread with a simple question... No need to post code.
What happens with nested interrupts enabled and other interrupts happening? Is there a priority or any interrupt will be executed onside my ISR.

On an AVR if you enable interrupts inside an ISR they will be handled when they occur according the their priority. As there is just a single flag controlling the interrupt enable ALL interrupts that occur will be handled, possibly even the one you are already handling if that occurs again.


Rob

Rob, what I am doing here is designing a remote device that talks over a Xbee module to a station. The station sends commands using a protocol where data is encapsulated with SYNC command, device ID to which it wants to talk too, command description and data and finally checksum.
On my ISR I am buffering the whole message and then once I reach checksum y call a parsing function that save the data of the message to dynamic memory using malloc. All these is then buffered on a circular buffer so that if the remote device is busy with something else it will execute that message later. Remote device has a serial camera and a GPS. Only at that moment at the end of a message if when my ISR routine can be longer as it calls that parsing function.
That is the whole idea why I want to have nested interrupts enabled so that I am sure I do not miss any data on serial port.
Another thing that could be done is to move the parsing function outside the ISR but I decided to include it on the ISR and I do not want to modify it now.

Have you considered doing the same thing without using any interrupts and without using malloc?

...R

I thought of many different ways and decided to use this method.

What about noblock and Priority handling?

Looks like nobody can answer that but all can question the design :slight_smile:

Just saw Graynomad response.

tero2011:
Looks like nobody can answer that but all can question the design :slight_smile:

Perhaps there is a message there ???

...R

Another thing that could be done is to move the parsing function outside the ISR...

That is the recommended method and the "party line" on this forum. I don't necessarily follow the party line because all situations are different and it can make sense to have a lot of code in an ISR, after all if there is nothing else to do why not?

Maybe you should look at your timing to see if it's worth the risk of enabling nested interrupts, if the data is coming in at 300 baud you have about a week and a half to parse the packet before the next character comes in anyway.

I have to say though that in this case I will follow the party line, I think the ISR should just add chars to a FIFO and the main code should take chars from that FIFO and parse as required. That is a simple and compartmentalised interface.

What about noblock and Priority handling?

I've never heard of noblock so can't comment on that. The priority of interrupts is as per their order shown in the data sheet, and as I said before if you enable interrupts in the ISR then they will be handled, but if you are both adding and removing bytes from a FIFO you have to be very careful about all non-atomic instructions that deal with global elements of the FIFO, head and tail pointers are probably OK in themselves but any operations that use both have to be protected and as do things like counters that hold the number of bytes in the FIFO.

As for malloc(), are all the blocks the same size? If so why not just have an array of arrays for the data? If not how will you free the blocks without getting fragmentation?

If you have a FIFO of pointers to arrays there is no need to move data around at all, in general you try to avoid physically moving bytes, it's better to change a pointer.


Rob

tero2011:
I thought of many different ways and decided to use this method.
What about noblock and Priority handling?
Looks like nobody can answer that but all can question the design :slight_smile:

On my ISR I am buffering the whole message and then once I reach checksum y call a parsing function that save the data of the message to dynamic memory using malloc. All these is then buffered on a circular buffer so that if the remote device is busy with something else it will execute that message later. Remote device has a serial camera and a GPS. Only at that moment at the end of a message if when my ISR routine can be longer as it calls that parsing function.
That is the whole idea why I want to have nested interrupts enabled so that I am sure I do not miss any data on serial port.
Another thing that could be done is to move the parsing function outside the ISR but I decided to include it on the ISR and I do not want to modify it now.

Rob answered your interrupt question, only one flag and uC will service via priority not my time of arrival. This is not good for your design which means, one of:

  • the design is not appropriate for uC selected
  • you selected the wrong uC

Your software architecture is not appropriate for what you are attempting to do. Obviously, you have a good grasp of programming but perhaps a different hardware platform. Programming and Software Architecture are separate entities but only become apparent when moving between hardware platforms.

Be forwarned, calling malloc within an ISR is not prudent. Parsing within the ISR is message dependent which means if the parse interval is variable, you are standing in quicksand.

Just my opinion, but I would strongly suggest you change the software design.

Ray

Thanks all for your help.

My incoming messages cannot have more than a fixed length and I managed to measure the ISR execution time in microsec for the worst case scenario using a oscilloscope.
Right after entering the ISR i am setting one digital pin to 1 and 1 step before leaving the ISR I am clearing that digital pin.
Max width of that ISR pulse was 16 microsecs which is more than a acceptable ISR length for my case as my serial port is communicating at 57600 bps which means 1 byte every 174 microsec.

Thanks