I'm nearly freaking out in my attempt to generate precise timing on the ESP8266 CPU. Something seems to interrupt my code even though I thought I got rid of all interrupts (which should be the only source of interruption, shouldn't they?).
Here is my boiled-down example. Should be pretty self-explanatory: disable interrupts, and then output a pulse on GPIO5 by toggling the GPIO and waiting some time before that, while the GPIO is high and after that.
static void __attribute__ ((noinline)) pulse()
{
taskDISABLE_INTERRUPTS();
for (volatile int i = 0; i < 100; i++); // waste some time
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, BIT5); // GPIO5 = high
for (volatile int i = 0; i < 500; i++); // waste some time (pulse width)
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, BIT5); // GPIO5 = low
for (volatile int i = 0; i < 100; i++); // waste some time
taskENABLE_INTERRUPTS();
}
Now comes the fun part: when I run this function in a loop, several 100 times per second, what I expected to see on my oscilloscope was a 'rock-stable' pulse, nicely triggered, not moving at all.
What I'm seeing instead is this here:
Most of the time (99,x%) the pulse is just fine and stable, 94us in length. But sometimes, the pulse is 6us longer. And sometimes, it's about 2*6us longer. The screenshot was done using infinite persistence on the scope's display. It is clear that this is not some "random timing jitter", because 6us is quite a long time for a processor on 80 MHz, and it seems that the timing only varies in multiples of these 6us.
The only idea I can come up with is: something must be interrupting my code, stealing about 480 CPU cycles (= 6 us), and then giving control back to my code.
However my understanding was that once interrupts are disabled, nothing could potentially interrupt me here. I verified int the assembler code that "rsil a3,3" was emitted, so really all interrupts are dead.
Does anyone have a clue?
Greetings,
Roland