Arduino instruction timing

The Arduino documentation readily available on the web is extremely shy (to say the least!) about instruction timing (eg clock cycles per instruction) or anything that has to do with real time programming, like ISR latency among other things (yes, I have seen Bill Grundmann’s blog on the subject).

I'm working on a project where I need to measure time delays that range from tens of milliseconds to tens of seconds with a resolution of 10 microseconds or better, that's why I'm looking for this type of information.

After a few hours looking here and there, including in this forum, I realize that some form of relevant documentation must exist somewhere, as people are quoting numbers (not always the same !) about digital write delay or similar stuff for example. If someone could point me to the right location it would save me a few days of testing !

I could use stuff like : - A plain list of instructions with their timings, - An assembly code breakdown of the high level C instructions (this does exist, I know, where is it on my computer ?) - A description of which instructions use which internal interrupts, - A description of interrupt priorities.

Thank you - Grazie - Danke - Gracias - Merci

-A plain list of instructions with their timings,

See the AVR data sheets

  • An assembly code breakdown of the high level C instructions (this does exist, I know, where is it on my computer ?)

No, it doesn't exist - the optimiser will vary high-level constructs depending on context - there is no 1:1 fixed correspondence.

  • A description of which instructions use which internal interrupts,

Don't know what you mean by this - if you mean like the old 68K A and F-line instructions, the answer is "none".

  • A description of interrupt priorities.

As far as I know, all interrupts have equal priority.

(yes, I have seen Bill Grundmann’s blog on the subject).

Not surprisingly, I haven't - when you quote material like this, it is useful to others to quote links.

Thank you Awol for your answers, you are right, my message needs clarification:

  • AVR data sheets - If you mean the Atmega 328 data sheet or similar it does not tell me much about an instruction like "attachInterrupt" for example. If you mean another level of documentation that links the C instructions to their assembly code, please explain.

  • The optimiser will vary high-level constructs... - I fully realise that, I would be already happy enough to just look at what it has done for my own code (but this I will eventually find, I'm sure).

  • Instructions and internal interrupts - micros() for one depends on an internal timer interrupt (at least this is my current understanding), are there others ?

  • Interrupt priorities: my wording may not be correct but basically I mean this: if two interrupts occur at the same time which is serviced first ?

  • Grundmann - http://billgrundmann.wordpress.com/2009/03/02/the-overhead-of-arduino-interrupts/

Hope you can help.

jmkymoe: - AVR data sheets - If you mean the Atmega 328 data sheet or similar it does not tell me much about an instruction like "attachInterrupt" for example.

You will not be able to find that kind of documentation. There is not a one-to-whatever mapping of C expressions to AVR machine instructions.

  • The optimiser will vary high-level constructs... - I fully realise that, I would be already happy enough to just look at what it has done for my own code (but this I will eventually find, I'm sure).

Will will be converting ELF files to Assembly Listings. This should get you started... http://www.google.com/search?q=elf+assembly+site%3Aarduino.cc

  • Interrupt priorities: my wording may not be correct but basically I mean this: if two interrupts occur at the same time which is serviced first ?

Datasheet. Interrupts section. First page.

My opinion is that if you are worried about very detailed things like interrupt latency, you really should be over on AVR Freaks and talking to the AVR-GCC people – and reading the ATMEL literature – rather than monkeying around with Arduino. Arduino is great and everything, but is a whole level of training wheels beyond the bare metal that the O/P is looking for.

Awol : I've had a look at this elf file and it is just what I needed to link the Arduino code with the Atmega documentation. Thanks a lot, I'm sure this will answer all of my questions.

gardner : you may be right, given the real-time constraints of my application I may eventually have to revert to AVR-level coding. After all I do come from a world where a list of instructions put together is called a program, not a sketch! I'm giving Arduino a chance though because at least on the hardware side it solves a lot of my current breadboarding issues...

... and I'm impressed with the reactivity of contributors on this forum!

... and I'm impressed with the reactivity of contributors on this forum! ... Even though I'm not able to correctly understand who writes what: Coding Badly my apologies for Reading Badly and thank you for the elf hint.

My 2 cents...

No two interruipts happen simultaneously. If the code to process one interrupt runs long enough that the next interrupt is blocked then the second interrupt will wait for the first to complete. Similarly, if the main-line code spends a lot of time with interrupts disabled, then an interrupt can wait before it is executed.

I do not recall reading about the priority of interrupt delivery in the datasheet. Although, I was reading with different questions in mind, and there are 566 pages in the datasheet... you might find what you are looking for there.

Given it does not make much practical difference it might be 'unspecified' meaning the priority can be vary between versions of the CPUs without notice.

If the timing of an interrupt delivery is really super critical - then you can really only have one interrupt source in the system. As once an interrupt starts running, the priority of the running interrupt relative to the next interrupt is not relevant. The second interrupt ALWAYS waits until the first completes. The priority only makes a difference once there are two interrupts waiting - at which point the higher priority interrupt waits for a shorter time. At this point we have 3 interrupts running one after the other... and perhaps by the time they are done another interrupt is fired.

If you want to do super fast interrupts, using GNU-c/c++ the interrupt latency can be reduced to a few cycles - given you disable the prologue, manage your register use carefully, limit your code, and code in inline assembler and do not use the Arduino library. *** It is probably simpler to buy a faster processor. ***

The bare metal interrupt for Bill's example is...

// 3 cycle in pin sync // 3 in the interrupt vector

ISR(INT0_vect, ISR_NAKED) // dont save r0, r1, sreg etc { LED_OFF(); // results in CBI which does not affect SREG // two or three cycles here. // can not do much more here as no regs available... reti(); }

So about 1/2 the number of cycles.

If you want to use interrupts as intended in the Arduino environment, to allow your code to be informed of something that happened in the real world, without having to check the state of a pin all over the place, then the extra 50+ cycles should not matter.

They represent 3 (16Mhz) or 6 (8Mhz) microseconds...

============ Look up the ATMEGA 168 on the atmel website. There is a link to the instructions there.

There are special instructions for accessing bytes with a variety of address ranges - it is hard to give a flat statement of the number of instructions per line of code.

The best way is to look at the output of avr-dump of your compiled code... if you search for avr-dump on the forum you will find discussions on how to do this on your platform.

Two contadictions to my own post.

From the data sheet pg 9 :( A flexible interrupt module has its control registers in the I/O space with an additional Global Interrupt Enable bit in the Status Register. All interrupts have a separate Interrupt Vector in the Interrupt Vector table. The interrupts have priority in accordance with their Interrupt Vector position. The lower the Interrupt Vector address, the higher the priority.

dafid: No two interruipts happen simultaneously. If the code to process one interrupt runs long enough that the next interrupt is blocked then the second interrupt will wait for the first to complete.

It dosnt have to be that way, the low priority interrupt can enable interrupts at the very first instruction if that makes sense... as per a big machine.

I’m working on a project where I need to measure time delays that range from tens of milliseconds to tens of seconds with a resolution of 10 microseconds or better, that’s why I’m looking for this type of information.

AVR instructions are on the order of 65 nanoseconds each. For your timeframes, worrying about individual instruction times may not be necessary; set up a hardware timer for <10uS for your timing and see if your code runs “fast enough” or not. Note that the default micros() function should have a resolution of about 4 microseconds.

You’ll want the AVR Instruction Set document as well as the atmega328 datasheet if you want detailed information on each instruction’s operation.

I should have read what you are trying to accomplish. I got caught up in the replies and questions I missed what you want to actually do.

Timer 1 on the 328 has an "input capture unit" that is a perfect solution. I'm using it right now to get 16 MHz timings (0.0625 microseconds) of things happening on an ATtiny85 processor. No special software is needed; the hardware does all the heavy lifting.

Sorry but this is a completely noob question; noob to electronics and programming and microcontrollers, however it has my underpants in a bunch cause I want to know how one would know: The jmkymoe wants to know how fast the Arduino will process (to describe it broadly) and westfw just mentioned that run in the order of 65nanoseconds, then he also suggested to run the program and see if it executes the code fast enough...thing is, how would I determine/measure if the code is excecuted fast enough? Surely I must measure it with something to be able to compare it with something? Is this a short-ish answer or a very technical one?

Sorry for the un-related question but I can't help myself.

Most folks would use an oscilloscope. Toggle an output pin that's connected to oscilloscope. Ideally, a pin that can be toggled using a single machine instruction is used so the toggle-pin time can be easily subtracted (if necessary).

I don't have an oscilloscope so I use the "fast timing Sketch" describe above or the difference between millis (or micros) calls. In my case, I have to trust that my crystal is more accurate than what I'm trying to measure.

Make sense or did I confuse you even more?

Inprogress: how would I determine/measure if the code is excecuted fast enough? Surely I must measure it with something to be able to compare it with something?

One easy way is to put a loop around the code and run it 1,000,000 times. Then you can time it with a stopwatch or by counting seamonkeys. Comparing two ways of handling a calculation is pretty easy.

At a finer grain, you might put timers around things -- call millis() or micros() before and after and subtract.

At a still finer grain, you can watch things with a logic analyzer or oscilloscope.

Arduinos are actually very fast, and the main constraint on the software we write is the lack of RAM, and knock-on problems stemming from that. Back in the day I did mountains of useful work on a Trash-80 that Arduino would run rings around, except my Trash-80 had 48K of memory versus the measly 2K we have on atmega328.

Surely I must measure it with something to be able to compare it with something?

Sure. Ideally you test it over the full range of expected inputs in parallel with a trusted tool whose cost, difficulty of use, size, required expertise, etc are much worse than the Arduino (say, an oscilloscope or logic analyzer.) You compare the results, and if they match within the desired tolerance, you declare success and start churning out $30 pulse measurement boards to replace the $10k scopes.

Alternately, you can look at the actual code produced and figure out how long it could possibly take, to make sure that THAT will be within tolerance...

A lot of people start out thinking that they have to make their code as fast as possible, or as small as possible, but the truth is that success is "digital"; either it's fast enough to work and small enough to fit in your chip, or it isn't. You shouldn't really spend a lot of time "optimizing" until you need to. The Arduino is fast enough that measuring some number of milliseconds to 10microsecond accuracy MIGHT be doable even with the most naive and straightforward of code segments:

  while (digitalRead(pin)  == LOW)
     ; // wait for pin change
  starttime = micros();
  while (digitalRead(pin) == HIGH)
     ; // wait for pin to change back
  width = micros() - starttime;

(This is sort of questionable in this case. We know from other discussions that digitalRead() is about 20x slower than the fastest possible pin read, so each of those function calls might be "a couple of microseconds", which added together is getting close to that 10us accuracy we want. But it's not immediately out of the question, either.) (This wouldn't be true on all microcontroller platforms, of course. A Basic Stamp 1, for instance, only does "about" 2000 statements per second.)

Coding Badly's idea of using a hardware timer is the ultimate fastest-possible solution. A basic Stamp provides a "pulsin()" statement that can measure pulses in 10us increments to provided a similar capability. There's always "something" (ok. "usually".) (Come to think of it, the Arduino libraries provide a "pulseIn" function as well. It claims it should be callled "a few dozen microseconds" before the pulse actually occurs, and works on pulses as sort as 2us, but I have my doubts about the first part...)

Thank you again to all those who responded, there are several interesting suggestions and I’m going to use them. At this time I have not had the time yet to dive into all the details, what follows is just to clarify where I come from.

As said before I’m looking for a time measurement resolution of less than 10 microseconds; I am also looking for an accuracy better than 10 ppm, but this is less challenging, more on this later. So this is how I look at it:

  • Speed of execution of the Arduino: not a limitation.
  • 4 microseconds granularity of the micros() instruction: acceptable.
  • However micros() is interruption dependent and the micro counter no longer increments during an ISR (based on what I have understood so far; haven’t looked at the AVR doc in detail yet): that’s the part I have to understand given that my measurement trigger is an external interrupt. This is workable, I know how to write a minimal ISR but in Arduino’s case I’m not the only one at work: I need to understand how many cycles will come from the helping hand of the C compiler. That’s how I will know if I have to adjust the internal microseconds reading, and by how much, or if I have to rely on an entirely different mechanism like Timer1.

I'm familar with the software and hardware techniques that have been described for measuring intruction delays, they are useful, I understand their pros and cons and to cut a long story short when I use one of these techniques I also like to have a look at the actual assembly code for confirmation.

As for accuracy since I need an RTC anyway I’m going to use an accurate one, (2-5 ppm frequency accuracy) with a 1-hertz signal output that I’m going to use to calibrate the micros() counter: once a minute ? once an hour ? To be determined

Thanks for the explanations guys. Its still a bit above me at this point in time but I do understand the concept though XD

Sorry for the semi-hijack of your thread jmkymoe :wink: