It's ok to interrupt me, even on AVR  Don't write off AVR just yet.

It’s ok to interrupt me, even on AVR

Don’t write off AVR just yet. I just checked in code on the FastLED3.1 branch that allows interrupts to run w/WS2811’s. As with the teensy, if your interrupt handlers run too long while writing out a frame, that frame will get cut short. Of course, unlike the teensy, you only have a window of about 500 clocks to do your interrupt handling in (as well as the rest of the AVR interrupts).

This is what happens if one stares at the datasheets too long … or just long enough…

Any idea how Arduino’s HardwareSerial.cpp interrupt takes?

I think we’re about to learn how long a whole lot of different interrupt service routines take…

And now that there’s (finally?) an actual concrete, visible reason for ISR developers to return “quickly enough”, who knows? They might even start optimizing their ISRs! It could happen! (Ok, so I’m an optimist…)

Judging by the desire to claw my eyes out whenever I go reading through that code, i’m inclined to say “too long” :slight_smile:

Although from a quick skim of it, looks like it might be around a hundred clock cycles or so.

it may be i’m not being kind enough to gcc or the code. What I should do is look at a dump and count actual instructions/cycles.

But 500 clocks is a fair amount of time, when you think about it (and the real number is more likely closer to 600+ clocks)

This is basically the code that I had done originally when I couldn’t make it work the first time - it turned out I had mis-read something though and was doing my calculations for how long the gap had been all wrong. A strong argument for always going back at least a couple of times :slight_smile:

I just made a quick and dirty measurement here, pulsing a pin on entry/exit. Looks like Arduino 1.0.6 on Uno takes approx 2.3 us (or about 37 cycles) in its serial transmit interrupt. Serial receive is very similar. Looking at a disassembly of the elf, ISR epilog and prolog look like about 22 cycles each, the JMP in the vector tables adds 3, and as I recall, the AVR hardware takes about 3-4 to save context and 4 to return. I believe that adds up to about 92 cycles. Not as horrible as I’d thought (and remembered from older versions of Arduino).

I just repeated this test on Teensy++ 2.0. Years ago, I put a lot of work into optimizing my ISRs, so I’m now wondering if mine are still faster? … well, it’s looking like mine run for about 1.4 and 1.6 us. The disassembly shows my epilog & prolog push/pop 2 less registers than Arduino’s, so total of about 68 cycles for receive, about 71 cycles for transmit.

oh, but subtract 2 cycles from all those estimates, for the pin toggling lines at added! :wink:

So could I, for instance, set up an ISR to record a sample from the mic some number of times per second?

Funny, we were just discussing that very use case.
It looks like the answer is “Yes, you could probably do that” - by putting the ADC into free-running mode, with an interrupt at the end of each conversion. However, the slowest you can do that is 125kHz… and you don’t want that many samples. So in your ISR, you’ll have to do something like keeping a counter and throwing out (N-1) out of (N) samples, and just keeping 1 out of N. Or something.

Try it and report back! This is all totally uncharted territory.

There may be other way to get that interrupt too. Just make sure not to dilly-dally inside the ISR!

Also, avoid call other functions, unless they’re static inline. As soon as the compiler has to call anything, the register use for C calling convention grows the ISR’s slow epilog & prolog. Integer division usually counts as a function call, unless it’s unsigned with a const denominator.