disabling interrupts inside an ISR

Go To Last Post
23 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am throwing an interrupt every 100 clock cycles on Timer0.  I am doing something inside the ISR that may take more than 100 cycles to complete.  Am I asking for trouble if I disable interrupts with a cli() statement at the beginning of the ISR so the ISR wont get called again and start over before it finishes what it was doing, and then turning interrupts back on with an sei() statement at the end of the ISR?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

All AVR auto turn off interrupts when an IRQ is fired, and re-enable them upon exit.    Why would an IRQ ever be that long?   IRQ's should be as short as possible, do the long stuff in main.

 

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is a short "for" loop, but can have a large number of times through the loop.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Pretty bad practice. Quite un-recommended.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Show us your code, and someone will suggest ways to improve it.

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The solution is quite simple.  Set a flag in the ISR and do the loop in main. 

 

What sort of problems are incurred executing a long loop in an ISR?  What makes it such a bad practice? 

 

I like to write recursive algorithms too.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Since interrupts are disable while in the ISR, no other interrupts can be serviced.   This usually causes problems with expected behavior.  Keeping ISR's short prevents (helps prevent) Interrupt starvation situations.  

 

Recursion is ok, as long as you have the ram for it, sometimes a problem on small AVR's with limited ram for stack space.

 

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I guess that's sort of obvious.  O well.  Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you can't get it done in 100 clk , why a ISR for every 100 clk and not 200 clk or what ever is needed?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If your ISR activity can possibly be longer than the time allocated for the ISR (100 cycles), then you need to move to a faster CPU.   Like an 50MHz ARM.

 

If you're using assembly language, each interrupt has to push the current flash address onto stack, get the vector instruction, execute it, and store one or more registers on the stack.  That can take 12-15 cycles on each side of the actual ISR code.   A C compiler may be stacking many registers before the ISR activity.

 

At 16MHz clock speed, 100 cycles is 6.25 microseconds.   I agree that any ISR triggering at this rate should do nothing more than set a flag or change a counter variable.

Last Edited: Thu. Aug 18, 2016 - 09:46 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That, and the more complex the ISR is the more registers that must be saved and restored, so it goes even slower still. It doesn't take much for the ISR to take 100 clock cycles for even the shortest execution path.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I chose 100 as an example number for my question.  I didn't mean for it to be taken literally.  The actual number I am using is larger than that.  I just wanted to pose the original question in simple terms, and didn't expect to get everyone to take it literally.  Sorry for the confusion.  All of my questions have been answered.  The good information here is that interrupts are automatically disabled when an ISR is entered and re-enabled when it leaves.  I was doing it myself, and now I don't have to.

 

Thanks all 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:

If you can't get it done in 100 clk , why a ISR for every 100 clk and not 200 clk or what ever is needed?

 

 

^^^^^That.

 

If you can tolerate missing an interrupt then you have too many interrupts happening.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

???

It a timer ISR!

 

But OP got his info, so over and out.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Even if you move the work out of the ISR and only have it triggered by a flag that the ISR sets then you still face an issue if the processing of one event takes longer than the time between events unless you can stack up a number of triggers then finally perform all the work during a "lean time" between events. But if the processing is constantly slower than the events you need to reduce the processing or do something to make it operate quicker (like a new CPU as suggested above).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

O well, sometimes you just have to break the rules to do what you want to do.  It is sort of like the old "go to" statement in FORTRAN, which became a bad practice because you could write impenetrable code using it.  You could also do some interesting things, too.  If I don't have any other important conflicting interrupts in my algorithm, and I let my ISR run over in a way I understand, then it may be a bad practice, but nobody is going to throw me in jail for it, and if my code does what I want then I am fine with it.  What's important is to know how it works and work around it if necessary, IMO.

 

Thanks for everyone's help and comments.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey Cliff,

I tried setting a flag to 1 in the ISR when the interrupt is thrown.  The calculation is started in main() if the flag is set to 1, and changes the value of the flag to 2.  In the ISR, if the flag has the new value = 2 nothing happens.  When the main() calculation is finished it sets the flag to 0, so the ISR knows the calculation is finished and is ready for a new calculation, so when the interrupt is thrown, the ISR sees the flag is now = 0, and sets the flag to 1 to start the calculation.  Crude maybe, but gets the job done and doesn't violate good programming practices.  What do you think?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sounds like a plan. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why not just a 0 and 1 flag? What purpose does the 2 value serve that the 1 can't by itself?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why not just a 0 and 1 flag? What purpose does the 2 value serve that the 1 can't by itself?

Good point.  I thought I had a reason, but now I cant think of it.  If it comes to me I will let you know.  Thanks. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's only "bad practice" if you don't understand the consequences. Here is the problem with what you suggest:

 

When you disable interrupts, the interrupt flags still "accumulate", so to speak. They are set, but sit dormant without interrupting the system until interrupts are enabled again. So if you disable them at the beginning of your ISR that's totally fine, it will allow the entire ISR to execute uninterrupted. But you should realize that immediately after enabling them again at the end there will likely be an interrupt waiting to be serviced, which will immediately go off. It's likely then, that the only code that will ever get executed is that inside the ISR. Which is fine, but kinda strange.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Because of the structure of the ISR an AVR will execute one instruction from "main" before it take the ISR "again".

 

This is for simple single stepping.

 

If you want to avoid this end the ISR with SEI just before the IRET (or RET), then the (I)RET is the instruction that is the debug one ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Edmundsj,

Well, that is pretty interesting.  I guess it makes sense the bit in the appropriate register is set when the interrupt gets thrown again, and then the ISR gets serviced as soon as it finishes.  I might have to put a delay in the ISR to see if I can make this happen on purpose.  So far my ISR executes fast enough that everything works fine.  Thanks for that.