Discuss here different C compiler set ups, and compiling executables for the ESP8266

User avatar
By rhaenel
#22935 Hi all,

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.

Code: Select allstatic 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:

Image

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
User avatar
By jcmvbkbc
#23002
rhaenel wrote: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?

Looks like Espressif SDK started to use NMI recently (starting with v.1.1.0), if you're using that or later SDK version that may be the reason.
User avatar
By kenn
#23005
rhaenel wrote: 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?)


From what little (ok more than that) we do know about the ESP8266 and the Espressif SDK (sort of an RTOS)... I've always considered it a programmable wifi peripheral, rather than a completely accessible microcontroller.

Until we know more, if I had a need for precise timing (PWM or whatever), I would find the extra dollar to add a dedicated 8-bit microcontroller to provide that.
User avatar
By joostn
#23011 I don't know why this happens, but you can generate precise timing loops using the CCount register:

Code: Select all   unsigned int getCCount()
   {
      unsigned r;
      asm volatile ("rsr %0, ccount" : "=r"(r));
      return r;
   }

ccount is updated every clock tick.

This still won't help if the interrupt occurs in the final 6 us though.