0

I am using Arduino Uno with Atmel Atmega328. I am using micros() function in Arduino IDE to measure time taken for execution. Here is my code:

void setup() {
    Serial.begin(9600);
}

void loop() {
    unsigned long a = micros();
    for (unsigned long j = 0; j < 100; ++j);
    Serial.println ((micros() - a));
    delay(1000);
}

The output comes as 4. But if I increase the number of iterations in the for loop to say around 1000000000 it still shows that for loop takes same time of 4. Is there a function which I can use to measure time properly in arduino?

1 Answer 1

6

The compiler has realized that your loop doesn't do anything useful and therefore optimized the whole thing away. Thus you are just timing how long it takes to do nothing. (You didn't get a result of zero, because calling micros will itself take time).

BTW, the granularity of micros is 4 µs, so you won't get a reading of 1 or 2. The code actually probably only took a couple of microseconds.

You need to do something that the compiler thinks "does something", like this:

void setup() {
    Serial.begin(115200);
}

volatile byte b;

void loop() {
    unsigned long a = micros();
    for (unsigned long j = 0; j < 100; ++j)
      b++;
    Serial.println ((micros() - a));
    delay(1000);
}

By making b volatile the compiler cannot decide that b isn't doing anything useful, so now the timings make sense.

I got 72 for 100 iterations and 144 for 200 iterations.


Is there a function which I can use to measure time properly in arduino?

Your time measurement is fine. Your interpretation of the results indicates you didn't realize how smart the compiler is. :)


You can see what the compiler did if you examine the generated code:

    unsigned long a = micros();
  d8:   0e 94 d2 00     call    0x1a4   ; 0x1a4 <micros>
  dc:   6b 01           movw    r12, r22
  de:   7c 01           movw    r14, r24
    for (unsigned long j = 0; j < 100; ++j);
    Serial.println ((micros() - a));
  e0:   0e 94 d2 00     call    0x1a4   ; 0x1a4 <micros>
  e4:   ab 01           movw    r20, r22
  e6:   bc 01           movw    r22, r24

As you can see, between the two calls to micros there isn't any sort of loop.

To find the assembled code you can follow the steps documented here.

Basically, turn on "verbose compiling" which will show near the end of the verbose output the full pathname of the ".elf" file. Then use a command (terminal) window to enter this command:

avr-objdump -S xxx.elf

You may want to redirect the output to a file:

avr-objdump -S xxx.elf > myfile.txt

Depending on how the Arduino IDE was installed you may have to find the pull pathname of avr-objdump and use that instead of just the program name.

2
  • 1
    To force iterations I ususally use for(...) { asm volatile("nop"); }.
    – Majenko
    Jan 28, 2018 at 11:38
  • Good idea. In reality the OP probably wants something "real" timed eventually so the problem will just go away when the loop does something useful.
    – Nick Gammon
    Jan 28, 2018 at 20:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.