Disturbed digital out at 4Mhz on Arduino NANO I've written a simple program - it generates signals over Port D at 4 MHz:

#include &lt;Arduino.h&gt;

int main(void) {

    DDRD = B11111111;
    PORTD = B00000000;

    while (true) {
        PORTD = 0;
        PORTD = 5;
        PORTD = 10;
        PORTD = 15;
        PORTD = 20;
        PORTD = 25;
        PORTD = 30;
        PORTD = 35;
        PORTD = 40;
    }
    return 0;
}


and this is the signal coming out on D4:


I've modified the program by inserting NOP after each assignment to POTRD:

#define NOP __asm__ __volatile__ ("nop\n\t")

int main(void) {

    DDRD = B11111111;
    PORTD = B00000000;

    while (true) {
        PORTD = 0;NOP;
        PORTD = 5;NOP;
        PORTD = 10;NOP;
        PORTD = 15;NOP;
        PORTD = 20;NOP;
        PORTD = 25;NOP;
        PORTD = 30;NOP;
        PORTD = 35;NOP;
        PORTD = 40;NOP;
    }
    return 0;
}


and now signal looks fine, but frequency is limited to 800 KHz:


What is the reason for interference at 4 MHz? Is there a limitation to maximal frequency on digital out? I do not really need it for some particular project, just wanted to know it.

I've asked this question on stackoverflow, but then I've discovered this dedicated forum so... I've decided to try it out ;)
This is not a limitation of the Arduino: you can toggle a pin on every clock cycle. It's a synchronization problem between the generated signal and the triggering of the scope. Your scope displays several traces superimposed, and it synchronizes them on the rising edges, but since those are unequally spaced, it gets out of sync with the full period of the signal. By adding a few nops you reached a lucky synchronization in your second version of the code.

The simplest solution is to set the scope mode to Single instead of Normal. Then it only displays a single trace and synchronization is not an issue anymore.

Another option would be to use one of the bits of PORTD as a trigger
signal. This bit should cycle only once inside the loop. PD5 should
work in the current version of your code. Configure the scope for
external trigger and feed this signal into its TRIG input.