disable_irq not effective

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: disable_irq not effective

Post by Roberthh » Wed Oct 03, 2018 9:47 am

Setting the trigger to a single slope only just about halves the "locked" count. BUT:
A look into the code improves knowledge:
Changing this line of the code by adding hard=True:

Code: Select all

p14.irq(trigger=Pin.IRQ_FALLING, handler=callback, hard=True)
the phenomenon also disappears. It seems that the parameter hard has disappeared from the documentation.
B.t.w: The relevant section in machine_pin.c is:

Code: Select all

                if (pin_irq_is_hard[p]) {
                    mp_call_function_1_protected(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p]));
                } else {
                    mp_sched_schedule(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p]));
                }
So you see, for a soft interrupt, the handler is scheduled, while for a hard interrupt, it is called immediately. As you know, there are pro con cons for both options.

P.S.: triggering on both slopes with a short pulse and hard interrupt causes trouble,

jmi2
Posts: 21
Joined: Mon Oct 01, 2018 9:31 pm

Re: disable_irq not effective

Post by jmi2 » Wed Oct 03, 2018 4:18 pm

Hello all,

Thanks for explanation of hard and soft. Was looking for it multiiple times in docu and also in google, but without success. Should be really documented.

Is someone creating ticket to fix, or in worst case document the behavior for disable_irq?

i had to remove WDT too, otherwise board reboots randomly, usually short after test. It's relict from past.

Still, i'm newby in micropython (and also in microcontrollers) - can python do reordering of statements execution? (googling for this returns lots of list sorting etc instead). If it can do, can i (partially) prevent it (eg. in java we have synchronized and volatile)?

thank you
best regards
jmi

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: disable_irq not effective

Post by Roberthh » Wed Oct 03, 2018 5:11 pm

As far as I know, Python, at least MicroPython, does not reorder statements. And even in other languages I have doubts, whether a function call and an assignment following it would be swapped, simply because the side effects of that call may not be known.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: disable_irq not effective

Post by pythoncoder » Thu Oct 04, 2018 5:16 am

@Roberthh I wonder if the lack of documentation is deliberate? Is there some problem with setting hard True? On the face of it, it seems like an important option. Would setting hard improve the latency measurements we did?
Peter Hinch
Index to my micropython libraries.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: disable_irq not effective

Post by Roberthh » Thu Oct 04, 2018 5:36 am

@pythoncoder: I think it was documented in the past. I remember the discussion around it. To collect some aspects:
hard=True: faster response; interrupt context, meaning e.g. no memory allocation#
hard=False: slower response; normal code execution context; no limitation on what can be done, e.g. memory allocation is possible
The hard=True mode should have a shorter latency, but not as short as the STM32, because there might still be a delay because the code to be executed has to be cached in from flash.

jmi2
Posts: 21
Joined: Mon Oct 01, 2018 9:31 pm

Re: disable_irq not effective

Post by jmi2 » Thu Oct 04, 2018 6:49 am

I just tried few times with hard=True and False and with True i wasn't able to reproduce a problem. Thanks a lot.
triggering on both slopes with a short pulse and hard interrupt causes trouble
what kind of trouble?

Soft is a problem. I guess disabling IRQs will disable them on HW level, but if handler call is already scheduled, it'll be called, even if IRQ is already disabled. Maybe it would make sense to delay such calls, until IRQ is enabled again. But don't know, if it's easily possible to change.

btw. in java even function call can become inlined during runtime and further optiomized by reordering etc. Hence i was suspecting it as possible reason.

thank you
best regards
jmi

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: disable_irq not effective

Post by Roberthh » Thu Oct 04, 2018 7:37 am

what kind of trouble?
In that case: strange error messages like: "cannot find module xxy", where xxy is the name of the actual script.
That could be cause by a second interrupt occuring before the handler finished the first one. Still strange, because interrupt should be blocked until the handler has finished.

jmi2
Posts: 21
Joined: Mon Oct 01, 2018 9:31 pm

Re: disable_irq not effective

Post by jmi2 » Thu Oct 04, 2018 10:25 am

update:

i connected two pins and used PWM to generate signal instead.

Code: Select all

import micropython, machine, time
from machine import Pin

micropython.alloc_emergency_exception_buf(100)

p14 = Pin(14, Pin.IN, Pin.PULL_UP)

p12 = Pin(12, Pin.OUT)
pwm12 = machine.PWM(p12)
pwm12.freq(500) # frequency must be between 1Hz and 1kHz.
pwm12.duty(900) # duty cycle is between 0 (all off) and 1023 (all on), with 512 being a 50% duty

changesCountUnlocked = 0
changesCountLocked = 0
locked = False


def callback(t):
    global changesCountUnlocked
    global changesCountLocked
    global locked

    if locked:
        changesCountLocked = changesCountLocked + 1
    else:
        changesCountUnlocked = changesCountUnlocked + 1


p14.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=callback, hard=True)

for loop in range(500):
    irq_state = machine.disable_irq() # Start of critical section
    locked = True

    a = 1;
    for loop in range(100):
        a = a + a;

    locked = False
    machine.enable_irq(irq_state) # End of critical section
    time.sleep_ms(10)


print ('changes locked:', changesCountLocked)
print ('changes unlocked:', changesCountUnlocked)
i had locked=0 all the time, but once i got 2. (still got copy from console to see code and result)
(for me no issues with importing modules etc, but i'm on esp8266)
After this i tried many more times also with different delays while locked and/or unlocked and with different frequency and duty, all without success to reproduce again.

jmi2
Posts: 21
Joined: Mon Oct 01, 2018 9:31 pm

Re: disable_irq not effective

Post by jmi2 » Thu Oct 04, 2018 1:05 pm

now i wonder, how hard=False actually works.

On interrupt, is called logic, which only schedules my own callback. How is it technically achieved, that it gets invoked? I mean, main program is running in long loop - how does it happen, that it gets interrupted and something else can run?

From forums about C programming for ESP i remember, it was necessary to call some special methods to release CPU to make it handle wifi etc.
So it looks like main program is normally not interrupted by anything (unless by interrupts).

So how is that handled in micrypython case?
I really would like to see much deeper documentation for micropython. Is there any?

thank you
best regards
jmi

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: disable_irq not effective

Post by pythoncoder » Fri Oct 05, 2018 10:00 am

The document on writing interrupt handlers is here.
Peter Hinch
Index to my micropython libraries.

Post Reply