-
I have read the article https://docs.micropython.org/en/latest/reference/isr_rules.html but have one question that wasn't clear from there. If I have a critical section in my main code that disables interrupts, updates a variable that is shared with the ISR, and then re-enables interrupts.... What happens if the interrupt fires while interrupts are disabled? Will it be missed? Or will the ISR be called after the interrupts are re-enabled? |
Beta Was this translation helpful? Give feedback.
Replies: 10 comments 17 replies
-
I was playing with this code, pin interrupt without debouncing routine.
Running on MicroPython v1.20.0-283 ESP32-S3 at 24MHz. The test is to touch GPIO-00 to GND and record the output.
From these results, we can conclude that the irq is not being captured and is not queued up during the period of So we want the priode between |
Beta Was this translation helpful? Give feedback.
-
I cannot see how you came to your conclusion, and you did not tell how you created the IRQ events. From previous test I know, that the IRQ latency for Pin.irq() at an otherwise idling ESP32 is 100µs - 400µs. Other reports much longer latencies, up to several 100 ms. |
Beta Was this translation helpful? Give feedback.
-
My setup is low-tech and simple. Using a female-male Dupont wire, I connect the female end to the GPIO-00 pin. As I mentioned earlier, the test was done by touching the male end to GND. Above is a simple test script. Anyone who is interested can experiment and test the results for themselves. I do not know how the interrupts were queued in between the irq disable and enable. I will take your word for it if you say they were queued. For all practical purposes, these are what I know.
Touching GND will naturally cause the voltage level at GPIO-00 to fluctuate. The result shows this. This is how the interrupts were generated. |
Beta Was this translation helpful? Give feedback.
-
It is interesting to note that mpconfigport.h:
modmachine.c:
Now it all makes sense. |
Beta Was this translation helpful? Give feedback.
-
As a direct test the following setup came to mind: Like: from machine import Pin
import micropython
micropython.alloc_emergency_exception_buf(160)
pin1 = Pin(14, Pin.OUT, value=0)
pin2 = Pin(14, Pin.OUT, value=0)
def isr1(pin):
state = machine.disable_irq()
pin2(1)
pin2(0)
machine.enable_irq(state)
print('Pin1 risen')
def isr2(pin):
print('Pin2 risen')
pin1.irq(isr1, trigger=Pin.IRQ_RISING, hard=True)
pin2.irq(isr2, trigger=Pin.IRQ_RISING, hard=True) which works on the pyboard: I know that on the Pico there are pin has risen flags and pin has fallen flags for every pin that are like an event storage. Now I repeated on the Pico W and observed, that only Seems like the first interrupt was taken over? It seems to be a bug. |
Beta Was this translation helpful? Give feedback.
-
For comparison with the ESP32 results, you must not use |
Beta Was this translation helpful? Give feedback.
-
Is this what you really want, i.e. pin1==pin2==Pin(14) I did the same test on the ESP32-S2 but used pin1 = Pin(1) and pin2 = Pin(2), the result is
as expected |
Beta Was this translation helpful? Give feedback.
-
As discussed above, the ESP32 is a little bit complicated because it only uses "soft" interrupts. So there are three parts here.
In some sense the exact same thing is implemented at two levels -- a low-level thing sets a flag (interrupt source, or scheduler), which the execution loop (the CPU, or the VM) will notice.
If interrupts are disabled, then the C handler will not be invoked, i.e. (2) above. The hardware may still set the pending bit for this IRQ, which means that the ISR can still be invoked when interrupts are enabled again.
It depends. For example, multiple different interrupt sources might share the same pending bit. Or the interrupt source may fire multiple times. So if you were relying on this to count the number of rising edges, then yes, you will miss interrupts. Or if you were waiting for events from multiple pins, and they happen to share the same IRQ line, then you might only see one. But in the simplest possible case, yes, you will still see a single interrupt. It's easy to verify this by triggering e.g. a pin edge while interrupts are disabled. You will see the handler invoked when they are re-enabled. |
Beta Was this translation helpful? Give feedback.
-
"...multiple different interrupt sources might share the same pending bit" So how can we determine which interrupt sources share a bit? For example, when a I2S completed interrupt is fired, how can we tell if its the same interrupt bit as, say, the pin-edge interrupt bit? |
Beta Was this translation helpful? Give feedback.
-
OK, I figured it out (and learned a lot in the process)...
I don't know if there is any solution to this, as I guess everything is working "as designed", but it's an unfortunate interaction. |
Beta Was this translation helpful? Give feedback.
@ma261065
As discussed above, the ESP32 is a little bit complicated because it only uses "soft" interrupts.
So there are three parts here.
machine.disable_irq()
. The C function schedules the Python handler.In some sense the exact same thing is implemented at two levels -- a low-level thing sets a flag (interrupt source, or scheduler), which the execution loop (the CPU, or …