Pulse output timing accuracy?

I was curious to see how fast can be the Arduino in the loop generating a square wave. So I have connected the oscilloscope to an Arduino Uno and this test loop:

bool high_state = true;
unsigned long curr_time = 0;
unsigned long prev_time = 0;

const unsigned long high_width = 1 * 1000; // micro seconds
const unsigned long low_Width = 1 * 1000;  // micro seconds

void loop()
{
  curr_time = micros();
  if( high_state){
    if( curr_time - prev_time >= high_width){
      digitalWrite( PINOUT, LOW);
      high_state = false;
      prev_time = curr_time;
    }
  }
  else { // low state
     if( curr_time - prev_time >= low_Width){
      digitalWrite( PINOUT, HIGH);
      high_state = true;
      prev_time = curr_time;
    } 
  }
}

With 1000 us each half of the wave:

Zooming in:


The error is around 2us ~ 4us, more or less.

Then with amplitude of each half reduced to 100 us:

And reduced to 10 us:


Erros is always 2 ~ 5 us.

Then I tested with this minimal loop to see how fast can it switch:

bool high_low = true;
void loop()
{
  digitalWrite( PINOUT, high_low);
  high_low = !high_low;
}

The amplitude of each half was: 3.180 us The total is similar to the error before.


I added 8 lines with millis() and some calculations in temp variables, then the amplitude increased to 4.6 us.

But, adding Serial.print:

bool high_low = true;
void loop()
{
  digitalWrite( PINOUT, high_low);
  high_low = !high_low;
  Serial.print("Olakease!");
}

Then amplitude of each half was: 760 us
Printing longer text the amplitude was longer, more than 1 ms.