Timing of various functions on ATMEGA 328P chip (Arduino Uno, Arduino Nano, etc) [stub]

Hi, I spent some time today with my Oscilloscope and testing various functions of the ATMEGA chip. I thought it would be worth it to someone else out there for me to share my findings. These are taken with TekTronix TDS 2024C Oscilloscope, I used a digitalWrite (pin, HIGH); digitalWrite (pin, LOW); sequence to serve as the time marker and then just ran various sequences after that in order to see how long it would take to repeat the digitalWrite(pin, HIGH) command... Since this allows for a detectable signal by the scope.

Pretty basic stuff and if anyone is interested in a more advanced functionality/sequence I'd be happy to test for you!

Here are the results:

Execute a digitalWrite(pin, value); ~4.1uS
Execute a digitalRead(pin); ~7uS
Execute a Serial.print(“”); ~4uS PLUS ~1.04mS per character printed (example; Serial.print(“hello”); 5 characters so it takes ~5.204mS. NOTE: same timing regardless of baud-rate
Execute analogRead(pin); ~112uS
Execute analogWrite(pin, value); ~8.4uS
Generate a random number; random(); ~50uS
Execute math functions; examples; INT =+ 1, VAR = sqrt(VAR), cos(), sin(), tan(); no perceptible time change

Execute a Serial.print(""); ~4uS PLUS ~1.04mS per character printed (example; Serial.print("hello"); 5 characters so it takes ~5.204mS. NOTE: same timing regardless of baud-rate

...but only if the transmit buffer is already full.
Not sure why it's the same value, irrespective of bit rate.

Execute math functions; examples; INT =+ 1, VAR = sqrt(VAR), cos(), sin(), tan(); no perceptible time change

Need to try harder. You're fighting the optimiser.

ElectricLove:
Pretty basic stuff and if anyone is interested in a more advanced functionality/sequence I'd be happy to test for you!

Please post the program you used to produce your results and explain how you use the 'scope to do the measurements

I would be interested to see the results for digitalWriteFast() and digitalReadFast() from the digitalWriteFast library

...R

Robin2:
Please post the program you used to produce your results and explain how you use the 'scope to do the measurements

I would be interested to see the results for digitalWriteFast() and digitalReadFast() from the digitalWriteFast library

...R

Here is one way to measure code timing:
https://forum.arduino.cc/index.php?topic=445951.msg3597772#msg3597772

larryd:
Here is one way to measure code timing:

Indeed. But how did the OP do it ?

...R

Robin2:
Indeed. But how did the OP do it ?

...R

These are taken with TekTronix TDS 2024C Oscilloscope, I used a digitalWrite (pin, HIGH); digitalWrite (pin, LOW);

I'd prefer to see the OP's program and his/her own description of the timing process.

...R

Robin2:
I'd prefer to see the OP's program and his/her own description of the timing process.

...R

The code is super basic; just activate the respective pins and run the short program. I used the digitalWrite High followed by digitalWrite Low in order to create a visible time-stamp on the Oscilloscope, the length of that time-stamp also represents the amount of time it takes for a digitalWrite High... digitalWrite Low command to execute.

Then I just put different functions in after that part of the code and used the scope to identify how much time between the peaks passed by, if it went from 4uS to 8uS then we can identify that it took 4uS for whatever was added to execute.

It is super basic but here it is...

"
void setup()
{
Serial.begin(9600);
pinMode(7, OUTPUT);
}

void loop()
{
digitalWrite(7, HIGH);
digitalWrite(7, LOW);
//WHATEVER FUNCTION WE ARE MEASURING TIMING OF
}
"

And, yes regardless of whether Serial.begin(value) is set to 9600 or 115200 or even 250000; the results of the timing of Serial.print(""); are the same...

I will try the digitalWriteFast commands and see what difference it makes.

Also; what do you mean by "fighting the optimiser" give me a math function to test and I'll be happy to see the effect...

ElectricLove:
Also; what do you mean by "fighting the optimiser" give me a math function to test and I'll be happy to see the effect...

If the compiler sees that the result of a calculation is never used it just leaves the calculation out of the code.

One way to deal with that is to declare your variables volatile as in

volatile int myVal;

...R

Robin2:
Please post the program you used to produce your results and explain how you use the 'scope to do the measurements

I would be interested to see the results for digitalWriteFast() and digitalReadFast() from the digitalWriteFast library

...R

To test digitalWriteFast()

Executed the following code:

"
#include <digitalWriteFast.h>

#define PIN 12

void setup()
{
volatile byte pin;
pinModeFast(PIN, INPUT);
pinModeFast(PIN, OUTPUT);
digitalWriteFast(PIN, LOW);
digitalWriteFast(PIN, HIGH);
pin = digitalReadFast(PIN); // save a proper high/low value
}

void loop()
{
digitalWriteFast(PIN, HIGH);
digitalWriteFast(PIN, LOW);
}
"

And results are, wow it is WAY faster than a digitalWrite()

~504nS

I've attached a screenshot of the scope reading; I got a different scope yesterday which I am trying out today and so this is not taken on the TekTronix but is instead a Siglent SDS1104X-E; I double-checked for sanity that the digitalWrite(); function was still ~4.1uS as discovered previously.

digitalWriteFast.png

Robin2:
If the compiler sees that the result of a calculation is never used it just leaves the calculation out of the code.

...or the compiler may simply substitute a constant, calculated at compile-time.

So here is the updated list of values;

Execute a digitalWrite(pin, value); ~4.0uS
Execute a digitalRead(pin); ~7uS
Execute a Serial.print(“”); ~4uS PLUS ~1.04mS per character printed (example; Serial.print(“hello”); 5 characters so it takes ~5.204mS. NOTE: same timing regardless of baud-rate
Execute analogRead(pin); ~112uS
Execute analogWrite(pin, value); ~8.5uS
Generate a random number; random(); ~50uS
Execute math functions; examples; INT =+ 1, VAR = sqrt(VAR), cos(), sin(), tan(); ~250nS
Execute a digitalWriteFast(pin, value); ~500nS
Starting Loop() over; ~250ns

Execute math functions; examples; INT =+ 1, VAR = sqrt(VAR), cos(), sin(), tan(); ~250nS

Four cycles at 16MHz?

Dream on

AWOL:
Four cycles at 16MHz?

Dream on

What am I doing wrong?

I run this code:

"
#include <digitalWriteFast.h>
#define PIN 14
void setup()
{
volatile byte pin;
pinModeFast(PIN, INPUT);
pinModeFast(PIN, OUTPUT);
digitalWriteFast(PIN, LOW);
digitalWriteFast(PIN, HIGH);
pin = digitalReadFast(PIN); // save a proper high/low value
}
void loop()
{
volatile int myVal;
digitalWriteFast(PIN, HIGH);
digitalWriteFast(PIN, LOW);
//myVal = tan(6000);
}
"
and get 500nS between the start of digitalWrite events (refer to attached image)

Then run this code:
"
#include <digitalWriteFast.h>
#define PIN 14
void setup()
{
volatile byte pin;
pinModeFast(PIN, INPUT);
pinModeFast(PIN, OUTPUT);
digitalWriteFast(PIN, LOW);
digitalWriteFast(PIN, HIGH);
pin = digitalReadFast(PIN); // save a proper high/low value
}
void loop()
{
volatile int myVal;
digitalWriteFast(PIN, HIGH);
digitalWriteFast(PIN, LOW);
myVal = tan(6000);
}
"

and get 750nS between the start of digitalWrite events (refer to attached image)

Since the only difference is whether or the myVal = tan(6000); (and time is same even if it is tan(1)) that means that the action of myVal = tan(6000); took exactly 250nS;

How else would you explain this?

ScopeWithMath.png

ScopeWithoutMath.png

tan(6000); is a compile-time constant, and you never use it.

You can verify this by looking at the compiled object code.

Please, start thinking.

What am I doing wrong?

Apart from not using code tags?

larryd:

It would be good if you could eliminate the int to floating point conversion.

2019-02-13_14-47-27.jpg

Thanks

And, yes regardless of whether Serial.begin(value) is set to 9600 or 115200 or even 250000; the results of the timing of Serial.print(""); are the same...

This is extremely unlikely, and does not match the behavior of a simple test sketch I put together:

void setup() {
  Serial.begin(256000);
  pinMode(13, OUTPUT);
}
void loop() {
  digitalWrite(13, HIGH);
  Serial.println("hello");
  digitalWrite(13, LOW);
}