How fast will an interrupt trigger after being enabled?

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

The AVR datasheets say, that after RETI and SEI, there is always at least one instruction executed until a (potentially pending) interrupt is being serviced.

However, to be able to calculate interrupt latencies exactly - and to be able to write optimal code - we need to know more. The following questions are outstanding:

  • does the above apply to situations where the I flag in SREG is changed through changing whole SREG (i.e. through OUT, STS, ST, etc.)? There is ample code out there working out of this assumption (e.g. avr-gcc functions prologue/epologue), and hints here and here, but I cannot find any Atmel-originated information stating clearly that this is the case, i.e. this may unexpectedly change in the future.
  • Does the above apply only to the global interrupt flag I? In other words, what happens if a single interrupt is enabled through setting its respective enable flag? If this interrupt is pending at the moment of enabling, will its routine called immediately, or will there be at least one instruction executed after the enabling instruction?
Could please somebody point me to a piece of information I might have been overlooked?

Or, if there is no such, could please the Atmel insiders reading these lines get the Atmel Norway crew to publish a binding explanation, maybe in a form of a short appnote? (I know I could post a question through the support website, but I find this to be a bit more important to all AVR developers than an answer to be communicated to me personally.)

Thanks,

Jan Waclawek

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

Quote:

Could please somebody point me to a piece of information I might have been overlooked?


I think you are overlooking that your questions aren't meaningful when you look at the whole picture. It sounds like you are trying to count down to the last cycle. But interrupts can occur at any time, and the current instruction must be completed. In general terms (and one doesn't know when the interrupt occurs with relation to the AVR clock cycle) that is 1-3 cycles in normal circumstances. It could be several more in unusual circumstances such as EEPROM read.

Your second point should be easy enough for you to test yourself--have the I bit set, have the IF bit set, enable the IE bit, and set a port bit with the next instruction. In the ISR, set another port bit. Look at the bits on the 'scope. when does the first one go high--before or after the ISR?

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Lee wrote:
It sounds like you are trying to count down to the last cycle.
Is anything wrong with that?

Lee wrote:
But interrupts can occur at any time, and the current instruction must be completed. [...] that is 1-3 cycles in normal circumstances. It could be several more in unusual circumstances[...]

If a sequence with disabled interrupts takes longer than the 3 cycles (or whatever it is in the "unusual case") - which is nothing unusual - its duration becomes dominant in determining the worst case interrupt latency, i.e. it does not matter that there are so many instructions which "disable" interrupts for 3 cycles.

I don't say there are many applications where counting to the last cycle matters, but there are such out there and it would be good to know whether we can rely on the described behaviour or not.

Lee wrote:
Your second point should be easy enough for you to test yourself[...
Oh of course I could do that. And then I would know that interrupt A on AVR model B silicon revision C works in this or that way. I don't believe you would approve using the "I tried and it worked" principle in your work, would you?

Jan

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

In most of my work, a single cycle not accounted for kills the entire program, and I found AVR interrupts to be a real problem until I did this...

; SAVE STATUS REGISTER
in r16,sreg ;1
push r16 ;2

; EQUALIZE INTERRUPT LATENCY
lds r16,tcnt1l ;2
cpi r16,10 ;1
brlo LATFIX1 ;1/2
LATFIX1:
cpi r16,11 ;1
brlo LATFIX2 ;1/2
LATFIX2:
cpi r16,12 ;1
brlo LATFIX3 ;1/2
LATFIX3:
cpi r16,13 ;1
brlo LATFIX4 ;1/2
LATFIX4:

As you can see in this segment (which is in the ISR), it equalizes the 1-4 cycle jitter, making AVR interrupts as smooth as PIC interrupts.

With this equalizing code, your interrupt will be cycle exact no matter what the main loop does.

This example assumes the ISR is triggered by Timer1, but any trigger source could be used and the timer just read to equalize the routine.

Brad

I Like to Build Stuff : http://www.AtomicZombie.com

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

Sorry for butting in on "Wek's" question..

This is an interesting thread..

Just wanted to know.. for the above "Code Example"..

What is it doing exactly.. ???

Just waisting Time ???

"We look for things.. Things that make us go."

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

Yeah I was thinking the same thing, then I remembered that the conditional branches use 1 clock or 2 clocks, depending on if the condition is true. So depending on the value of the timer register, it spends more time in the ISR.

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

A OK..

I See it now.. at first all I seen was r16's
didn't see it was loaded with the tcnt1l

---- Now that I see that, it could also be

Not waiting for the 'IRQ' flag

but rather

Catching each cycle with code, and executiing blocks of code.. pending the tcnt1l value

The above code may be a very "non elaborate" example

But any way..

Maybe AtomicZombie will explain.. later..

because "He is Smart"

"We look for things.. Things that make us go."

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

When the ISR is entered, it will have a latency of up to 4 cycles depending on the instruction that must first complete. By reading TCNT (or any timer), you can determine this latency. In my example, a certain number of cycles are wasted depending on the timer value, hence equalizing the ISR so that after the equalizer, there is no random latency.

I use this in my video systems were a single lost cycle out of tens of thousands kills the image. This equalizer works perfectly every time.

Of course, you need to know your "base" value and then reset the timer after the EQ, or be entering the ISR due to a timer event.

Also, some larger AVRs have instructions with 5 cycles, so you would need one more branch in the EQ for those.

So yes, the program wastes time... a few cycles, but it does this to make sure the ISR code is executed at precisely the same time with no jitter no matter what the main loop may be doing.

Cheers,
Brad

I Like to Build Stuff : http://www.AtomicZombie.com

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

Quote:

Is anything wrong with that?

Well, let's hear the utility of that. 'Zombie's video work counts, but hardly a mainstream app. And apparently his program has no EEPROM reads during the time an interrupt might fire.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Yaa. I think very unique application also..
video needs to be accurate for sure..

But nice to know about it, in case one day.. I become smart.

"We look for things.. Things that make us go."

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

Quote:
does the above apply to situations where the I flag in SREG is changed through changing whole SREG (i.e. through OUT, STS, ST, etc.)?
I would say yes. It is the setting of the interrupt that matters, not how it was set.
Quote:
what happens if a single interrupt is enabled through setting its respective enable flag? If this interrupt is pending at the moment of enabling, will its routine called immediately, or will there be at least one instruction executed after the enabling instruction?
According to the simulator (version 2), there is one instruction run before the interrupt occurs. Also, if both the global and individual flags are set. there is one instruction run after the interrupt flag is set. Again, this is the simulator, so cum grano salis. But it does make sense that there would be the same latency in all circumstances (and so not really have anything directly to do with the global interrupt flag, but simply one clock to determine that there really is an interrupt).

Regards,
Steve A.

The Board helps those that help themselves.

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

Not commenting on any previous post..
And I hope I uderstand the purpose for
"AtomicZombie's" delay routine.

Hard to say what solution to offer (the OP) "wek"

as no exact info is given on the app. (He is doing)

But something like "AtomicZombie's" delay routine..
to keep the count ODD or EVEN before enabling the
IRQ again should work.

As long as the IRQ events he is trying to trap are not too fast..

Cuzz.. a delay such as "AtomicZombie's" could kill "wek's" App.. by adding delays.

(Just a thought)

"We look for things.. Things that make us go."

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

Quote:
Hard to say what solution to offer
There is no general solution to know beforehand what the latency will be, only ways to figure out (and maybe compensate for it) afterwards.

Regards,
Steve A.

The Board helps those that help themselves.

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

Koshchi wrote:
There is no general solution to know beforehand what the latency will be, only ways to figure out (and maybe compensate for it) afterwards.

Ya.. Too bad..

Personaly my apps are very very small.
Push button speed.

Never thought about this "latancy" thing.. (no need for me)

perhaps never.

AtomicZombie hinted something "as smooth as PIC interrupts"

Don't they have this "latancy" issue ?.. (or what ?)

Dare I say.. Design flaw with AVR ? :oops: (OH GOD FORGIVE ME!!) :twisted:

"We look for things.. Things that make us go."

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

Quote:
Dare I say.. Design flaw with AVR ?
No, merely a different design. As stated above, very few apps would ever require absolutely consistent latency. Note that this does not mean no latency, there must be a finite time for the micro to react to an interrupt.

Regards,
Steve A.

The Board helps those that help themselves.

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

Ah.. Good..

Had me worried there for a second..

Not that I would ever stop using AVR

I Would never RISC it :)

"We look for things.. Things that make us go."

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

Besides the equalisation problem, there is a (probably bigger) group of applications, where latency must be kept at minimum, and then it is also important to know HOW MUCH that is.

For example, in one design I use SPI slave in an AVR which does not have an inbound byte buffer on SPI. Having a 3 cycles higher latency on the SPI interrupt in this application would mean either bytes to be lost from time to time, or speed to be halved, both with detrimental consequences on complexity or throughput (in the first case a packetizing protocol with retries would have to be devised, in the second the master simply has to go down with speed).

---

Regardless of how often used, Atmel (the AVR core designers) does have this information. As Steve said above, it is most probably a direct consequence of how the interrupt controller is implemented. It is only a matter of publishing this information in a way that we can rely on it, now and in the future.

JW

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

AtomicZombie wrote:

; SAVE STATUS REGISTER
in r16,sreg ;1
push r16 ;2

; EQUALIZE INTERRUPT LATENCY
lds r16,tcnt1l ;2
cpi r16,10 ;1
brlo LATFIX1 ;1/2
LATFIX1:
cpi r16,11 ;1
brlo LATFIX2 ;1/2
LATFIX2:
cpi r16,12 ;1
brlo LATFIX3 ;1/2
LATFIX3:
cpi r16,13 ;1
brlo LATFIX4 ;1/2
LATFIX4:

So each and every line of code always runs , irrespective of branch or no branch ? But takes 1 or 2 clk cycles each time, depending on each compare result ?

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

Conditional branch takes 2 cycles when taken, and 1 cycle when not taken. The same target instruction in Zombie's code is reached in 1 or 2 cycles depending on the condition. This is the way he aligns the latency time to a fixed value regardless of what instruction (1-, 2-, 3- or 4-cycle) has been interrupted - the timer value reflects the interrupted instruction length in cycles.

Of course this assumes the timer is running only off an Fcy/1 frequency.

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.

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

Quote:
Regardless of how often used, Atmel (the AVR core designers) does have this information. As Steve said above, it is most probably a direct consequence of how the interrupt controller is implemented. It is only a matter of publishing this information in a way that we can rely on it, now and in the future.

JW

It must be the 1 instruction pipeline that does it!

And about max speed on SPI:
Nothing stops you from checking if a 2. byte is received at the end of your interrups (as long you clean up). All in all that save time.

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

and that lead to the next, what happen after a CLI can next instruction get interruptet?

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

No. The datasheets are absolutely clear in this.

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

Quote:

where latency must be kept at minimum, and then it is also important to know HOW MUCH that is.

Again, you can't come up with a hard number because of the variation in the length of the current instruction. Since that is commonly 2 cycles (1-3) worrying about a partial cycle or even a whole one doesn't seem to have any value.

As mentioned, in a normal complete app there is stuff going on in the mainline, so the interrupt point is purely arbitrary. I've already mentioned EEPROM reads which stop the processor for four cycles. So unless you have a controlled non-interrupt instruction sequence one neds to design-in a safety factor.

Once you tell me how you are going to quantify and make constant the time to finish the current instruction each time, then I might have more interest.

Now, instead of spending hours/days/weeks on this for a critical SPI slave app, I'd probably think something like this: "My SPI slave can get packets at any time, and I want to have as high an SPI rate as practical. This is an AVR so the slave can only be at clk/4 anyway, or xx MHz in my case. That is y.yy microseconds/byte. SPI packets are of modest length, so when triggered by the interrupt for the first byte I'm going to gather the rest of the packet in a tight loop eliminating the SPI interrupt-servicing overhead which is about 20 cycles on a Mega164."

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Another approach to get jitter free interrupts:

Go to sleep prior the interrupt was fired.
E.g. use COMP-B Interrupt (attribute NOBLOCK) to go to sleep, some cycles prior COMP-A interrupt.
Then you can consider larger delays, e.g. by atomic access on the main.

And you can write it in C.

Peter

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

Quote:

Another approach to get jitter free interrupts:

Go to sleep prior the interrupt was fired.


Certainly, and I don't think it was mentioned. wek seems to be concerned with minimum latency time. If the app is doing nothing but waiting for the SPI packet, then that would give a predicable response to the first SPI byte.

But what about succeeding SPI bytes? Do you follow the SLEEP with a string of NOP that will be consumed for the length of the entire SPI packet? Or a string of SLEEP and then disable sleep when the packet is complete?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:
If the app is doing nothing but waiting for the SPI packet, then that would give a predicable response to the first SPI byte.

On my opinion the AVRs are fully unusable as SPI slave.

If you need a SPI-slave, e.g. the AT89LP4052 was ideally suited.
It has buffered SPI and interrupt priorities.

If you need to connect AVRs togehter, you can use UART, I2C or CAN, but never SPI.

My post above was related to this:

https://www.avrfreaks.net/index.p...

Peter

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

theusch wrote:
Certainly, and I don't think it was mentioned. wek seems to be concerned with minimum latency time.
Indeed. IMHO that's a more common (and more prohibitive) constraint than interrupt jitter.

The application normally runs, and there are also other interrupts active. Standard latency calculations apply.

sparrow2: There is no point in checking other received bytes in the SPI ISR - the issue is, that SPI does not have an Rx double buffer so the span between ISRs is 1 byte long, but the latency has to be less than one bit time.

JW

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

danni wrote:
On my opinion the AVRs are fully unusable as SPI slave.
Tell my boss ;-) Well, once I worked out the latencies, it works flawlessly - why would that be otherwise, this IS a deterministic machine. However, I don't have an interrupt disabled sequence during runtime on that particular application.

But okay, SPI does not count, then have an external interrupt and you MUST act within a given time span (various shared buses).

It's quite irrelevant what is the application - one has to strive for minimum latencies and sometimes it goes down to the single cycle.

And, as I said, technically it's easy from Atmel's side to provide the precise information.

JW

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

Jan,

You were probably typing while danni was posting.

The simple answer is that AVR's are not suitable for emulating hardware SPI slaves. Most of Atmel AT89's are unsuitable too. except for the AT89LP4052.

You can use the USART, but I would guess that many apps want both USART and SPI.

You can try STM8S or of course pretty well any ARM device.

As far as I can remember, I could keep up fairly well by polling the SPIF and disabling all interrupts. But most SPI masters expect to get immediate replies. This is not possible to do with an AVR regular SPI.

Quote:
And, as I said, technically it's easy from Atmel's side to provide the precise information.

I think that they do provide the info. They do not provide the hardware.

David.

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

david.prentice wrote:
Quote:
And, as I said, technically it's easy from Atmel's side to provide the precise information.

I think that they do provide the info. They do not provide the hardware.

David,

Please don't sidetrack the thread because of one particular example I mentioned. I was asking for information on the how the interrupts work, not for recommendations as per SPI (but thanks, if I would ever go there again, I'll use a different hardware or protocol).

No, they don't provide the information I asked for in the OP. Or at least I could not find it.

JW

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

wek wrote:
For example, in one design I use SPI slave in an AVR which does not have an inbound byte buffer on SPI. Having a 3 cycles higher latency on the SPI interrupt in this application would mean either bytes to be lost from time to time, or speed to be halved,
Is there a reason you can't just add 4 extra cycles between bytes?
That would cost you a lot less than half the speed.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

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

skeeve wrote:
Is there a reason you can't just add 4 extra cycles between bytes?
Again and again: particular solutions to the particular example I mentioned are little relevant to the original topic of this thread.

Besides, whatever method I chose, I must know whether it is appropriate. For example I may add 4 cycles, but how do I know whether that would suffice? And why would I want to add 4 cycles if it is not necessary?

I know I can simply assume the worst case and stay a bit further inside the safe side all the time, but again and again, why would Atmel refuse to publish a simple information making the application of their chips better?

JW

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

Sorry, I thought that the IRQ behaviour was fairly clear.

The AVR completes its current ISR() and restores I with the RETI instruction.
It then executes the next regular instruction.
If there is an xxIF and xxIE and I is set in SREG, it will enter another ISR().

That 'intervening' instruction can be 1,2,3 cycles long. And if the EEPROM has just been started, could be more.

If that 'intervening' instruction happened to be CLI, or SBI xx,xxIF then the next ISR() will not occur.

The odds of your ISR()'s just happening either side of a CLI instruction must be fairly low.

If you want to stop the RETI behaviour, you disable all the xxIE bits inside the ISR() (or clear the xxIF bits).

Or you overrule the C compiler and leave the ISR() via RET. This ensures the CLI status.

I am sure that you have a real problem to solve. It is easier to attack the problem than to calculate worst cases.

David.

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

Why the AVRs are not suited as SPI-slave:

The AVR has no SPI transmit buffer and thus the slave get an interrupt on the last SCK edge
and must prepare the next byte until the next SCK edge.

Asuming an interrupt need 20 cycle to do so (AVR-GCC), the fastest SPI clock can only be
XTAL_slave / 40.

Assuming there are two other interrupt sources in use, which may need about 100 cycle, then the fastest SPI clock reduce to
XTAL_slave / 440.

Assuming the slave AVR run on its internal 8MHz,
so the SPI clock must be below 18kHz.

Thus I think, I2C at 400kHz or 100kHz can do the job many times better.

Peter

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

Quote:
sparrow2: There is no point in checking other received bytes in the SPI ISR - the issue is, that SPI does not have an Rx double buffer so the span between ISRs is 1 byte long, but the latency has to be less than one bit time.
The SPI does have a read buffer, so you have a full byte time to read it before it is lost.

Regards,
Steve A.

The Board helps those that help themselves.

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

Quote:

Please don't sidetrack the thread because of one particular example I mentioned. I was asking for information on the how the interrupts work, not for recommendations as per SPI

LOL--one last shot and then I'm out.

So, if you post "I use up all my processor doing polled UART comms; how can I make them fastest?", no-one better suggest using interrupt-driven?

Go ahead, discard all the suggestions. Shaving a cycle off ISR servicing time is putting lipstick on a pig for SPI. You get better mileage building the routine into the vector table, for example. Or poll succeeding bytes as I suggested.

Quote:

On my opinion the AVRs are fully unusable as SPI slave.

I don't know if I'd go as far as "fully unusable" but certainly clumsy at best for all but the simplest of work.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Quote:
Sorry, I thought that the IRQ behaviour was fairly clear.

The AVR completes its current ISR() and restores I with the RETI instruction.
It then executes the next regular instruction.
If there is an xxIF and xxIE and I is set in SREG, it will enter another ISR().

That 'intervening' instruction can be 1,2,3 cycles long. And if the EEPROM has just been started, could be more.

If that 'intervening' instruction happened to be CLI, or SBI xx,xxIF then the next ISR() will not occur.

The odds of your ISR()'s just happening either side of a CLI instruction must be fairly low.

If you want to stop the RETI behaviour, you disable all the xxIE bits inside the ISR() (or clear the xxIF bits).

Or you overrule the C compiler and leave the ISR() via RET. This ensures the CLI status.

I am sure that you have a real problem to solve. It is easier to attack the problem than to calculate worst cases.

David.

I don't think it's the hole story :)

I don't have my avrboard here but I just made a project and ran it with simulator2 (that is the best I can do for now).
The program enable a fast timer interrupt.
The main have 50 sei(); in a row (and I checked the ASM is 50 SEI in a row). And the "AVR" take the interrupt.

Then I made 50 sei(); cli(); and there it don't take the interrupt, so I actually think the simulator does it as the chip!

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

sparrow2 wrote:
I don't think it's the whole story :)
It is not. Worse; the whole story is not published by Atmel.

And that is what this thread was supposed to be all about, nothing else.

JW

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

Here is a thing I will like someone to test!

As we know after SEI or RETI the AVR will do one instruction before a hanging interrupt is taken.

So if we want fast interrups (don't want to run 1 instructions from main) the end of the interrupt should be :

;interrupt code
SEI
RETI

And the simulator agree !

Can anyone verify on a real chip?

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

Quote:
Can anyone verify on a real chip?
avr-gcc does this trick quite often, so yes, it has been verified many times.

Regards,
Steve A.

The Board helps those that help themselves.

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

Sorry I have only seen it do it around a piece of code that need to be atomic.
Can you show me a piece of C code that the avr-gcc compile to that sequence?