Very strange delay function

Hi,

I saw a guy instead of using delayMicroseconds he used this function below. Why? Is there any advantage in it?

void delay_1us()  
{
  __asm__ __volatile__ (
  "nop" "\n\t"
    "nop" "\n\t"
    "nop" "\n\t"
    "nop" "\n\t"
    "nop" "\n\t"
    "nop" "\n\t"
    "nop" "\n\t"
    "nop" "\n\t"
    "nop" "\n\t"
    "nop" "\n\t"
    "nop" "\n\t"
    "nop" "\n\t"
    "nop" "\n\t"
    "nop" "\n\t"
    "nop" "\n\t"
    "nop");
}

Is there any advantage in it?

The time that is wasted is an exact quantity. Each nop takes one clock cycle to complete. 16 * ~65 nanoseconds is 1 microsecond, which is not something that delayMicroseconds() can reliably deliver. Read up in the resolution that delayMicroseconds() promises.

By my testing delayMicroseconds() is no good if you need microsecond precision. It runs about 1.25µs fast. My guess is it used to be more accurate but got skewed by subsequent compiler optimization changes.

_delay_us(double) and __builtin_avr_delay_cycles(unsigned long) are very precise and likely to remain accurate through compiler updates.

Great, now I understand that :slight_smile:

matmanj:
By my testing delayMicroseconds() is no good if you need microsecond precision. It runs about 1.25µs fast. My guess is it used to be more accurate but got skewed by subsequent compiler optimization changes.

I have noticed that when LTO* is enabled and delayMicroseconds() is called with a constant value, it inlines the loop and precalculates the number of iterations, which makes the delay about 1 µs shorter (19 cycles @ 16 MHz to be exact).

  • link time optimization; enabled by default since AVR 1.6.12 (IDE 1.6.10)