ESP8266 Interrupt Latency

P. Short

Super Moderator
Staff member
I'm having problems with external interrupt latency in my 'DIY Oscilloscope" project using the Arduino IDE. I'm assuming that this is mostly due to the processor attempting to save and restore processor context at the entrance and exit from the ISR. Is there any way to reduce the ISR overhead? I'm guessing that it would involve reducing the context save/restore to the bare minimum needed by the ISR code, possibly by programming in assembly language (with Arduino IDE or some other development environment)?

Alternative, I might need to switch to an ESP32 module (or does this not reduce the latency problem somewhat, but not into insignificance)? The ESP32-cam looks like one possibility, although I would like it to have more than 10 I/O pins. Other candidates are "ESP32 Pico" ($15 from Adafruit), or TinyPICO (a bit expensive).

Edit: The other annoyance is the large amount of time that passes between the end of the 'loop' and re-entering it...seems to be about 6.5 uS.
 
Last edited:
I'm having problems with external interrupt latency in my 'DIY Oscilloscope" project using the Arduino IDE. I'm assuming that this is mostly due to the processor attempting to save and restore processor context at the entrance and exit from the ISR. Is there any way to reduce the ISR overhead? I'm guessing that it would involve reducing the context save/restore to the bare minimum needed by the ISR code, possibly by programming in assembly language (with Arduino IDE or some other development environment)?

Alternative, I might need to switch to an ESP32 module (or does this not reduce the latency problem somewhat, but not into insignificance)? The ESP32-cam looks like one possibility, although I would like it to have more than 10 I/O pins. Other candidates are "ESP32 Pico" ($15 from Adafruit), or TinyPICO (a bit expensive).

Edit: The other annoyance is the large amount of time that passes between the end of the 'loop' and re-entering it...seems to be about 6.5 uS.

I just noticed this on Stack and apparently ICACHE_RAM_ATTR has been changed to IRAM_ATTR in release 3.0.0 .
There appears to be many changes as of May 2021.

Have you updated the esp8266/Arduino ?
If not it's worth a look-see.
 
My code already had IRAM_ATTR instead of ICACHE_RAM_ATTR.

As far as esp8266/Arduino, I don't know what it is, nor how to determine what I have or how to update it if it's not the latest.
 
I would stop using the Arduino IDE and move to the Visual Code (Baby Visual Studio) plus PlatformIO. You can still build an Arduino based project or you can use the Espressif IDF directly which reduces ISR latency.
 
SInce I do all of my development on either Linux or FreeBSD, I think that VIsual Studio is out of the question. Maybe I'm missing something, but Espressif IDF seems to be geared towards ESP32. I'm not fixated on the Arduino IDE, but I'm not sure where to turn yet. Is there an Espressif development environment targeted to the ESP8266?
 
The sdk is for the 8266 .

Here is a good thread .

That thread wasn't helpful, it ended several years ago with things not working as far as I could tell.

I've got two possible solutions to my difficulty, which stemmed from a design decision to use interrupts in the Wemos (from the dsPIC33) on a continual basis to input data, and sending out Udp data from the foreground tp a PC for display. In the previous thought process I was going to read 16 bytes of data into the Wemos at a time from the ISR, resulting in one interrupt every 8 uS. The favored new design reads 24 bytes at a time, not 16, which reduces the number of interrupts and thus reduces the importance of the long 8266 interrupt overhead (presumably mostly due to context saving and restoring). I'll continue to look into other IDE's and SDK's over time.
 
That thread wasn't helpful, it ended several years ago with things not working as far as I could tell.

I've got two possible solutions to my difficulty, which stemmed from a design decision to use interrupts in the Wemos (from the dsPIC33) on a continual basis to input data, and sending out Udp data from the foreground tp a PC for display. In the previous thought process I was going to read 16 bytes of data into the Wemos at a time from the ISR, resulting in one interrupt every 8 uS. The favored new design reads 24 bytes at a time, not 16, which reduces the number of interrupts and thus reduces the importance of the long 8266 interrupt overhead (presumably mostly due to context saving and restoring). I'll continue to look into other IDE's and SDK's over time.


Good to know .
The thread was to merely point out the sdk usage for the 8266.

HERE IS A SNIP FROM THAT THREAD .

OK. So I was able to flash Esp8266 (NodeMCU) with almost same settings for Esp32 toolchain except I switched IDF_PATH to ESP8266_RTOS_SDK directory. All compiled fine just like CMake for esp32.
 
Last edited:
SInce I do all of my development on either Linux or FreeBSD, I think that VIsual Studio is out of the question. Maybe I'm missing something, but Espressif IDF seems to be geared towards ESP32. I'm not fixated on the Arduino IDE, but I'm not sure where to turn yet. Is there an Espressif development environment targeted to the ESP8266?

I think you might have misunderstood Martin comment on Visual Studio Code.
"Visual Studio Code" is a different product from Visual Studio and it is cross platform. This link should help you get up and running. https://code.visualstudio.com/docs/setup/linux

PlatformIO is a plugin for Visual Studio Code that does a pretty nice job and managing work flow and dependencies for your project. Once you have that all up and running you should be able to target either Arduino or IDF.
 
I think you might have misunderstood Martin comment on Visual Studio Code.
"Visual Studio Code" is a different product from Visual Studio and it is cross platform. This link should help you get up and running. https://code.visualstudio.com/docs/setup/linux

PlatformIO is a plugin for Visual Studio Code that does a pretty nice job and managing work flow and dependencies for your project. Once you have that all up and running you should be able to target either Arduino or IDF.

My google search led me to the MS site. I'll look into that later, thanks.
 
My google search led me to the MS site. I'll look into that later, thanks.

With the Arduino IDE it appeared that the background task (sending UDP packets over WiFi) was starved for cpu cycles, so I downloaded the visualstudio code and PlatformIO and installed them, and spent a few painful hours trying to get things going. After compiling and uploading my previous code to that environment, it appears that the interrupt latency and I/O speeds were essentially the same as with the Arduino build, so I suspect that I ended up using the Arduino logic, just accessed in a different SDK.
 
Which framework did you load in PlatformIO? If you check out this page: https://docs.platformio.org/en/stable/platforms/espressif8266.html and scroll down to Frameworks, it looks like there are a couple of variations of native expressif sdks.
Of course, I think that means you will lose any Arduindo references. I'm not sure if you're using any in your code.

So far I've only played with the esp32 using Arduino in PlatformIO so hopefully someone else has more information.
 
OK, that was the wrong framework, I'm trying to switch over to esp8266-nons-sdk framework, but the entire API seems quite different. What a pain.
 
With the Arduino IDE it appeared that the background task (sending UDP packets over WiFi) was starved for cpu cycles, so I downloaded the visualstudio code and PlatformIO and installed them, and spent a few painful hours trying to get things going. After compiling and uploading my previous code to that environment, it appears that the interrupt latency and I/O speeds were essentially the same as with the Arduino build, so I suspect that I ended up using the Arduino logic, just accessed in a different SDK.[/QUOTE

Here is a snippet that shows isr used from the sdk rather than Arduino .


Code:
#include "esp_common.h"
#include "esp_timer.h"
#include "gpio.h"
static os_timer_t some_timer;

static void timer_handler(void* args) {
   
    printf("timer");
}


static void intr_handler() {
   
    u32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
    gpio_pin_intr_state_set(GPIO_ID_PIN(12) , GPIO_PIN_INTR_DISABLE);
    GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(12) );

    //printf("a,");   
    portENTER_CRITICAL();
   
    //printf("b,");
    os_timer_disarm(&some_timer);
    os_timer_setfn(&some_timer, (os_timer_func_t *)timer_handler, NULL);
    os_timer_arm(&some_timer, 3, 1);
    //printf("c,");
    portEXIT_CRITICAL();
    //printf("d\n");

        gpio_pin_intr_state_set(GPIO_ID_PIN(12) ,GPIO_PIN_INTR_NEGEDGE);
}

void user_init(void)
{
    GPIO_ConfigTypeDef gpio_in_cfg12;
    gpio_in_cfg12.GPIO_Pin  = GPIO_Pin_12;
    gpio_in_cfg12.GPIO_IntrType = GPIO_PIN_INTR_NEGEDGE;
    gpio_in_cfg12.GPIO_Mode = GPIO_Mode_Input;
    gpio_in_cfg12.GPIO_Pullup = GPIO_PullUp_EN;
    gpio_config(&gpio_in_cfg12);

    gpio_intr_handler_register(intr_handler, NULL);
    _xt_isr_unmask(1 << ETS_GPIO_INUM);
}
 
I haven't had much success with the visualstudio/platformIO setup. What board and framework should I be using? At the moment I'm using d1_mini and esp8266-rtos-sdk, my code builds and downloads (to my Wemos clone) but I haven't been able to get the pins to wiggle.
 
I haven't had much success with the visualstudio/platformIO setup. What board and framework should I be using? At the moment I'm using d1_mini and esp8266-rtos-sdk, my code builds and downloads (to my Wemos clone) but I haven't been able to get the pins to wiggle.

I have not done what you are attempting Phil . I believe you just want to access to the sdk and specifically the user_interface.h. while using the Arduino framework .

The code to use this is as follows

Code:
extern "C" {
    #include "user_interface.h"
}



Hopefully Martin will explain .
 
Last edited:
Back
Top