Page 1 of 2

IRQ Startup latency

Posted: Thu Jan 10, 2019 6:26 am
by go4retro
I am seeing a similar issue as noted here:

The use case is a legacy bus interface, where the bi-directional nature of the bus is like I2S (open collector lines with pullups), but the data size is 4 bits.

The master will pull the "nybble" line low after placing data on the databus. 9.35uS later, it brings the "nybble" line high and checks to see if it is still low.

The esp32 needs to react to the line activity, and bring a corresponding output line (that is connected via a 74ls06 OC inverter) to the "nybble" line.

By checking on my logic analyzer, I see that the first events happens at time 0, and at T=9.35uS, the master brings the line high. At 17uS, the esp32 responds to the event and sets an IO line to respond, which is too late. It also takes 26uS to process the IRQ body, though I am using QueueSendfromISR in the body and the fact that the ISR takes 26uS to finish is actually OK (I assume there is startup cost to the QueueSend API).

Subsequent invocations of the IRQ handler appear to bring the IO response within 5uS, and executes the ISR body in 1.8uS. Thus, I know my code is working OK. And, if I recover from this issue without rebooting the esp32, subsequent communications works fine.

I tried to "prime" the ISR by generating an IRQ on the line before communication starts, but that did not seem to help. I am setting the GPIO first thing in my ISR.

I can work around the issue but creating a circuit that will hardware "ack" the event, but I am new to the esp32 and thought perhaps I am missing some small thing.

For reference, I am using GPIO_NUM_23 as my ISR input, setup as an IRQ via:

// I set up GPIO_NUM_23 as input with a pullup along with some other IO pins.
//hook isr handler for pin
gpio_isr_handler_add(GPIO_NUM_23 , isr_handler, NULL);

// trigger on negedge edge of pin
gpio_set_intr_type(GPIO_NUM_23 , GPIO_PIN_INTR_POSEDGE); //inverted logic

I used the blink example as my base, and added in the code from the gpio example to get going. FreeRTOS is running with 1 task.

I hated to bother folks with what I assume is a n00b question, but aside from the initial link, I didn't seem to find any relevant forum postings.


Re: IRQ Startup latency

Posted: Thu Jan 10, 2019 3:17 pm
by ESP_igrr
If the latency varies between the first and the subsequent ISR execution, then this is probably related to caching.

You can move the ISR and the functions it calls into IRAM, by adding IRAM_ATTR to the function definition, or using the Linker Script Generation feature (check "noflash" mapping: ... ation.html).

Re: IRQ Startup latency

Posted: Thu Jan 10, 2019 6:02 pm
by go4retro
I appreciate the response. I will do just that and test. Ironically, the code I copied to start the ISR had that in there, but an article I was reading at the time said that it was no longer necessary to use the modifier, so I left it out of the declaration.

Oh well, I guess it's better to see the effect and how to address it.


Re: IRQ Startup latency

Posted: Sat Jan 12, 2019 5:41 am
by ESP_Sprite
FYI, 'It's no longer necessarily' probably meant for normal (not ultra-low-latency) purposes. The issue initially was that interrupts would be enabled during SPI flash writes, and any interrupts that would not reside in IRAM would try to fetch code from the flash, which was unavailable because it's in the middle of a write. We solved that by disabling all interrupts not specifically marked as being in IRAM.

Your interrupt latency issue is a separate thing, and placing the interrupt in IRAM indeed should solve it.

Re: IRQ Startup latency

Posted: Sat Jan 12, 2019 6:24 am
by go4retro
Regrettably, it has returned. It was working fine after putting in IRAM_ATTR, and I got much further in development. Then, I added a second task to do some Wifi and TCP, and the issue returned.

I used the code in this example:

TO see how my code behved with some lwIP and Wifi happening...


Re: IRQ Startup latency

Posted: Sun Jan 13, 2019 11:58 am
by ESP_Sprite
1. Do you mark your ISR as being in IRAM when you allocate the interrupt? If not, it still will be disabled when flash is used.
2. Are all functions called by the ISR also in cache? (If not, you'll get crashes when you have done step 1.)

Re: IRQ Startup latency

Posted: Sun Jan 13, 2019 9:46 pm
by go4retro

static void IRAM_ATTR jim_isr_handler(void* arg) {

And, all variables and functions used in the ISR are marked as IRAM_ATTR.

It may be that I have to call gpio_set_level() at the very beginning of the ISR, and I suspect that's not in IRAM. So, pulling it from SPI flash makes the response too late.


Re: IRQ Startup latency

Posted: Sun Jan 13, 2019 10:21 pm
by WiFive
He meant did you also set ESP_INTR_FLAG_IRAM ... t-handlers

Re: IRQ Startup latency

Posted: Sun Jan 13, 2019 11:33 pm
by go4retro
WiFive wrote:
Sun Jan 13, 2019 10:21 pm
He meant did you also set ESP_INTR_FLAG_IRAM ... t-handlers
Ah, I didn't fully understand. No, I had not. I went back and changed it:


And, I moved all of the functions that it called into IRAM as well.


No change. Still 19uS too late to drop the IO line, and 29uS after the event occurred.

I wish I understood more about the internal workings in the CPU, because I may indeed be asking the system to perform beyond it's abilities. 29uS seems like too much time for an ISR to engage, but perhaps not, given all that is happening under the covers (FreeRTOS, the wifi subsystem running, lwIP on, etc.)

I considered reducing the test case down, but if it's not reasonable to get ISR invocation + GPIO_SET to be < 10uS, it seem better to work on another path to success.


Re: IRQ Startup latency

Posted: Sun Jan 13, 2019 11:35 pm
by ESP_igrr
You can also move any other function you call from your ISR to IRAM, such as gpio_set_level. To do this you can add a linker script fragment to your component
( ... ation.html).

Example linker.lf:

Code: Select all

archive: libdriver.a
    driver:gpio_set_level (noflash)
(And then also COMPONENT_ADD_LDFRAGMENTS += linker.lf in your