Interrupt handlers chaining on ESP32
Interrupt handlers chaining on ESP32
Hello,
I'd like to install my own interrupt handler (e.g. GPIO interrupt or RMT interrupt, one of the ETS_ interrupt sources), but also save previous handler address to call it after my ISR is finished.
Is this doable in ESP-IDF?
Another question is: if I save original interrupt handler entry, and then simply "j original_handler" can I get away with that?
I need to "intercept" some interrupts to count statistics (bytes transferred/received, errors, interrupt count etc)
Thanks!
PS: any relevant links with examples or just working code which works with interrupts, may be using xt_utils are greatly appreciated
I'd like to install my own interrupt handler (e.g. GPIO interrupt or RMT interrupt, one of the ETS_ interrupt sources), but also save previous handler address to call it after my ISR is finished.
Is this doable in ESP-IDF?
Another question is: if I save original interrupt handler entry, and then simply "j original_handler" can I get away with that?
I need to "intercept" some interrupts to count statistics (bytes transferred/received, errors, interrupt count etc)
Thanks!
PS: any relevant links with examples or just working code which works with interrupts, may be using xt_utils are greatly appreciated
Thanks!
Slava.
Slava.
-
ahsrabrifat
- Posts: 201
- Joined: Sat Jan 18, 2025 2:31 pm
Re: Interrupt handlers chaining on ESP32
You can hook into most interrupts in ESP-IDF, but the recommended way is not to directly patch the vector table. Instead, you usually register a handler with esp_intr_alloc() (or the newer esp_intr_alloc_intrstatus()) for the specific interrupt source.
-
MicroController
- Posts: 2669
- Joined: Mon Oct 17, 2022 7:38 pm
- Location: Europe, Germany
Re: Interrupt handlers chaining on ESP32
Only if both your handler and the original handler are written in assembly and use the call0 ABI.Another question is: if I save original interrupt handler entry, and then simply "j original_handler" can I get away with that?
Note that most interrupts are "pre-handled"/wrapped by the same assembly handler in the IDF which does some housekeeping and then dispatches to the actual individual ISRs (written in C/call4 ABI, so no tail-calling).
Re: Interrupt handlers chaining on ESP32
Yes, right, ESP-IDF handles, say GPIO interrupts via its own handler, which was once set via esp_intr_alloc(ETS_..)Only if both your handler and the original handler are written in assembly and use the call0 ABI.Another question is: if I save original interrupt handler entry, and then simply "j original_handler" can I get away with that?
Note that most interrupts are "pre-handled"/wrapped by the same assembly handler in the IDF which does some housekeeping and then dispatches to the actual individual ISRs (written in C/call4 ABI, so no tail-calling).
1. Which interrupt vector number is used for that? How interrupt number relates to interrupt source? For example, why Level5 interrupt maps to interrupt vector #15
2. If I inject my own binary code (saving original bytes) straight to the interrupt handler? I mean, I inject there something
"j my_interceptor_routine", then "j" from the interceptor to original code?
My problem is that I want to intercept certain interrupts, namely GPIO interrupt. User sketch may not use GPIO interrupts or it can register a global GPIO handler or it can use GPIO ISR Service and register per-GPIO interrupt. I'd like to keep application working as it should but intercept all GPIO interrupts before application can process them.
I did similar things on different archs (i386, powerpc) but esp32 is a bit different so I am seeking an advice.
Also I didn't understand why I should use call0 abi if I intercept interrupts by writing to the vector table. Why can't I do my stuff in my interceptor (increment counters) and then "j" to original entrypoint? Registers are saved at that point as I can understand so I am free to use any of them.
Thanks!
Slava.
Slava.
Re: Interrupt handlers chaining on ESP32
Thanks for the links. After looking into the sources I found that both xt_set_interrupt_handler and xt_set_exception_handler return previous handle, yay! So chaining seems to be possibleNote that most interrupts are "pre-handled"/wrapped by the same assembly handler in the IDF which does some housekeeping and then dispatches to the actual individual ISRs (written in C/call4 ABI, so no tail-calling).
Thanks!
Slava.
Slava.
-
MicroController
- Posts: 2669
- Joined: Mon Oct 17, 2022 7:38 pm
- Location: Europe, Germany
Re: Interrupt handlers chaining on ESP32
What I wanted to point out is that you cannot jump to a function when using the the windowed (call8/call4) ABI; each ENTRY instruction needs a corresponding RETW, and when your function has an ENTRY and you jump to another function, that'll be two ENTRYs but only one RETW.Also I didn't understand why I should use call0 abi if I intercept interrupts by writing to the vector table. Why can't I do my stuff in my interceptor (increment counters) and then "j" to original entrypoint? Registers are saved at that point as I can understand so I am free to use any of them.
If your function is an actual hardware-called interrupt handler, effectively call0 ABI, it cannot jump to a call4/call8 function. It can however jump to another similar interrupt handler provided that other handler also returns via RFE. So chaining interrupt handlers via jump is possible but only for lowest-level/hardware-called assembly handlers.
Re: Interrupt handlers chaining on ESP32
Ooh got it.What I wanted to point out is that you cannot jump to a function when using the the windowed (call8/call4) ABI; each ENTRY instruction needs a corresponding RETW, and when your function has an ENTRY and you jump to another function, that'll be two ENTRYs but only one RETW.
But if I am chaining interrupts which are compiled as call0 ABI, this is possible, right?
Making call4 or call8 from an interrupt handler is not possible, I assume.
Thanks for the information!
Thanks!
Slava.
Slava.
Re: Interrupt handlers chaining on ESP32
So, summarizing:
Xtensa interrupts vector table consist of entries "j Handler". If I change that to "j My_handler" and from My_handler I can do "j Handler".
My_handler must be written in assembler, because we don't need any prologue/epilogue. Question: can I get away with a C function which has __attribute__((naked))?
Xtensa interrupts vector table consist of entries "j Handler". If I change that to "j My_handler" and from My_handler I can do "j Handler".
My_handler must be written in assembler, because we don't need any prologue/epilogue. Question: can I get away with a C function which has __attribute__((naked))?
Thanks!
Slava.
Slava.
Re: Interrupt handlers chaining on ESP32
This won't help you much in solving your problem.
As far as I understand, you want to intercept specific interrupts from the peripheral.
Given that esp_intr_alloc(ETS_..) builds another interrupt table (this table is already from the usual chains of c-style functions) for interrupts for the peripheral, usually level 1-3, depending on the shared/level/cpu flags. you will have to disassemble each interrupt for belonging to the peripheral in order to understand what caused the interruption.
So if you want to log your handlers, just add a logger to them, if you want to log the handlers of the idf drivers (uart, rmt...), use the callback provided by the idf and insert the loggers there.
you can see how esp_intr_alloc makes a shared table, and you can also find the address of this table there.
As far as I understand, you want to intercept specific interrupts from the peripheral.
Given that esp_intr_alloc(ETS_..) builds another interrupt table (this table is already from the usual chains of c-style functions) for interrupts for the peripheral, usually level 1-3, depending on the shared/level/cpu flags. you will have to disassemble each interrupt for belonging to the peripheral in order to understand what caused the interruption.
So if you want to log your handlers, just add a logger to them, if you want to log the handlers of the idf drivers (uart, rmt...), use the callback provided by the idf and insert the loggers there.
you can see how esp_intr_alloc makes a shared table, and you can also find the address of this table there.
-
MicroController
- Posts: 2669
- Joined: Mon Oct 17, 2022 7:38 pm
- Location: Europe, Germany
Re: Interrupt handlers chaining on ESP32
Rather not. C needs a stack frame, the required size of which for a given function is determined by and known only to the compiler. A naked function does not set up a stack frame, so you'd have to do it manually; but you can't because you don't know how large it has to be.Question: can I get away with a C function which has __attribute__((naked))?
Edit: Also, the Xtensa gcc doesn't seem to support naked ("warning: 'naked' attribute directive ignored")
Who is online
Users browsing this forum: Applebot, Baidu [Spider], Bytespider, Qwantbot, YisouSpider and 4 guests