IRQ Startup latency
IRQ Startup latency
I am seeing a similar issue as noted here:
https://www.esp32.com/viewtopic.php?t=1108
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.
Jim
https://www.esp32.com/viewtopic.php?t=1108
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.
Jim
Re: IRQ Startup latency
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: https://docs.espressif.com/projects/esp ... ation.html).
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: https://docs.espressif.com/projects/esp ... ation.html).
Re: IRQ Startup latency
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.
Jim
Oh well, I guess it's better to see the effect and how to address it.
Jim
-
- Posts: 9764
- Joined: Thu Nov 26, 2015 4:08 am
Re: IRQ Startup latency
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.
Your interrupt latency issue is a separate thing, and placing the interrupt in IRAM indeed should solve it.
Re: IRQ Startup latency
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:
https://github.com/sankarcheppali/esp_idf_esp32_posts
TO see how my code behved with some lwIP and Wifi happening...
Jim
I used the code in this example:
https://github.com/sankarcheppali/esp_idf_esp32_posts
TO see how my code behved with some lwIP and Wifi happening...
Jim
-
- Posts: 9764
- Joined: Thu Nov 26, 2015 4:08 am
Re: IRQ Startup latency
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.)
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
Yep:
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.
Jim
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.
Jim
Re: IRQ Startup latency
He meant did you also set ESP_INTR_FLAG_IRAM
https://docs.espressif.com/projects/esp ... t-handlers
https://docs.espressif.com/projects/esp ... t-handlers
Re: IRQ Startup latency
Ah, I didn't fully understand. No, I had not. I went back and changed it:WiFive wrote: ↑Sun Jan 13, 2019 10:21 pmHe meant did you also set ESP_INTR_FLAG_IRAM
https://docs.espressif.com/projects/esp ... t-handlers
gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
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.
JIm
Re: IRQ Startup latency
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
(https://docs.espressif.com/projects/esp ... ation.html).
Example linker.lf:
(And then also COMPONENT_ADD_LDFRAGMENTS += linker.lf in your component.mk)
(https://docs.espressif.com/projects/esp ... ation.html).
Example linker.lf:
Code: Select all
[mapping]
archive: libdriver.a
entries:
driver:gpio_set_level (noflash)
Who is online
Users browsing this forum: asargent and 166 guests