Go Down

Topic: nanosecond delay functions - playing with volatile (Read 2080 times) previous topic - next topic

robtillaart


Today I played with the delayMicroseconds() function - http://arduino.cc/forum/index.php/topic,132983.0.html -  It seems to be difficult to get delays of 1 and 2 usec right. So I tried to make a function that delayed for exactly 1 usec and started experimenting with the volatile keyword in (for me) new ways.

This way I "fabricated" 4 functions:
- delay125ns();
- delay250ns();
- delay500ns();
- delay1000ns();

The timings are approx within 1% tested on a 16Mhz Duemillanove. I tested these functions by running them in a loop, first with one call , and then a second loop with 2 calls, so the difference is the time used by the functions as the loop overhead is subtracted too.

Note: There are better ways to implement these functions - using asm("nop"); - but this was just fun! :) 

The functions:
Code: [Select]

void delay125ns()
{
  volatile uint8_t x=0;
  return;
}

void delay250ns()
{
  volatile int x=0;
  return;
}

int delay500ns()
{
  volatile int x=0;
  return x;
}

int delay1000ns()
{
  volatile int x = 0;
  volatile int y = 0;
  return x+y;
}

// profi way to implement such delay functions
void d250ns()
{
  asm("nop");
  asm("nop");
  asm("nop");
  asm("nop");
}


The testprogram with functions: 

Code: [Select]
void setup()
{
  Serial.begin(9600);
  Serial.println("start...");
 
  unsigned long m;
  unsigned long n;
 
 
  Serial.println("delay125ns");
  m = micros();
  for (unsigned int i=0; i<16000; i++) delay125ns();
  m = micros() - m;
  n = micros();
  for (unsigned int i=0; i<16000; i++)
  {
    delay125ns();
    delay125ns();
  }
  n = micros() - n;
  Serial.print("Extra 1000 calls take: ");
  Serial.println((n-m)/16);

  Serial.println("delay250ns");
  m = micros();
  for (unsigned int i=0; i<16000; i++) delay250ns();
  m = micros() - m;
  n = micros();
  for (unsigned int i=0; i<16000; i++)
  {
    delay250ns();
    delay250ns();
  }
  n = micros() - n;
  Serial.print("Extra 1000 calls take: ");
  Serial.println((n-m)/16);


  Serial.println("delay500ns");
  m = micros();
  for (unsigned int i=0; i<16000; i++) delay500ns();
  m = micros()- m;
  n = micros();
  for (unsigned int i=0; i<16000; i++)
  {
    delay500ns();
    delay500ns();
  }
  n = micros()- n;
  Serial.print("Extra 1000 calls take: ");
  Serial.println((n-m)/16);


  Serial.println("delay1000ns");
  m = micros();
  for (unsigned int i=0; i<16000; i++) delay1000ns();
  m = micros() - m;
  n = micros();
  for (unsigned int i=0; i<16000; i++)
  {
    delay1000ns();
    delay1000ns();
  }
  n = micros() - n;
  Serial.print("Extra 1000 calls take: ");
  Serial.println((n-m)/16);
}

void loop()
{}

void delay125ns()
{
  volatile uint8_t x=0;
  return;
}

void delay250ns()
{
  volatile int x=0;
  return;
}

int delay500ns()
{
  volatile int x=0;
  return x;
}

int delay1000ns()
{
  volatile int x = 0;
  volatile int y = 0;
  return x+y;
}

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

PaulS

Does the presence or absence of the return statement make any difference? I typically do not include a return statement in a function of type void, since it will return anyway.

leo72


Does the presence or absence of the return statement make any difference? I typically do not include a return statement in a function of type void, since it will return anyway.

I think that robtillaart has based its counting mechaninsm on the declaration of variables and the usage of return statement.
If you look at his code, every function has a different combination of variable declaration and value returned.

PaulS

Quote
If you look at his code, every function has a different combination of variable declaration and value returned.

You mean the voids returned by delay125ns(), delay250ns(), and d250ns()?

retrolefty



Does the presence or absence of the return statement make any difference? I typically do not include a return statement in a function of type void, since it will return anyway.

I think that robtillaart has based its counting mechaninsm on the declaration of variables and the usage of return statement.
If you look at his code, every function has a different combination of variable declaration and value returned.


That's how I took it. A dump of the generated object code would show the actual instructions generated that make up the specific delay values sought.

Lefty

robtillaart

FYI, I focused more on the initialization of the volatile vars, and sought different ways to add cycles. Without volatile the compiler optimizes the functions away.

I will look if I can do a dump of the assembly/obj tonight but the forum is soooo sloooow at the moment.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart


For those interested, the output of objdump -d -S testDelayNanoSeconds.cpp.o is in the zip file attached.

have fun ;)





Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

leo72



For those interested, the output of objdump -d -S testDelayNanoSeconds.cpp.o is in the zip file attached.

have fun ;)







Interesting  ;)

Go Up