RP2040 PIO Pin change to HIGH do not works

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
beyonlo
Posts: 58
Joined: Thu Nov 26, 2015 8:03 pm

RP2040 PIO Pin change to HIGH do not works

Post by beyonlo » Tue Mar 22, 2022 1:27 am

Hi all

I have this function below from this PIO example https://github.com/raspberrypi/pico-mic ... nchange.py

Code: Select all

@rp2.asm_pio()
def wait_pin_low():
    wrap_target()

    wait(0, pin, 0)
    irq(block, rel(0))
    wait(1, pin, 0)

    wrap()
I would like to change that PIO function just to works on pin in high mode instead low. I readed this doc https://docs.micropython.org/en/latest/library/rp2.html about the commands of PIO, and changed to this code below:

Code: Select all

@rp2.asm_pio()
def wait_pin_high():
    wrap_target()

    wait(1, pin, 0)
    irq(block, rel(0))
    wait(0, pin, 0)

    wrap()
But not works. I did others modifications, but not success.

What is wrong?

I'm using RPICO with MicroPython version 1.8:

Code: Select all

>>> import os
>>> os.uname()
(sysname='rp2', nodename='rp2', release='1.18.0', version='v1.18 on 2022-01-17 (GNU 11.2.0 MinSizeRel)', machine='Raspberry Pi Pico with RP2040')
>>>
Thank you in advance!

beyonlo
Posts: 58
Joined: Thu Nov 26, 2015 8:03 pm

Re: RP2040 PIO Pin change to HIGH do not works

Post by beyonlo » Wed Mar 23, 2022 9:31 pm

I still have no success, could anyone help me?

Thank you.

GerryKeely
Posts: 5
Joined: Wed Feb 17, 2021 10:12 pm

Re: RP2040 PIO Pin change to HIGH do not works

Post by GerryKeely » Thu Mar 24, 2022 4:43 pm

Hi
I have tried your program with a push button on pin 20 which is connected between the pin and ground.
Also activated the pullup resistor on this pin and it works as expected.
ie in first case interrupt is generated when push button is pressed and in second case the interrupt occurs when the push button is released.
regards
Gerry

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

Re: RP2040 PIO Pin change to HIGH do not works

Post by pythoncoder » Fri Mar 25, 2022 10:09 am

It's perhaps worth pointing out that these examples detect pin changes and pushbuttons usually produce multiple pin changes due to contact bounce. There are better ways of handling pushbuttons and switches such as the uasyncio classes documented here.
Peter Hinch
Index to my micropython libraries.

beyonlo
Posts: 58
Joined: Thu Nov 26, 2015 8:03 pm

Re: RP2040 PIO Pin change to HIGH do not works

Post by beyonlo » Mon Mar 28, 2022 6:43 pm

GerryKeely wrote:
Thu Mar 24, 2022 4:43 pm
Hi
I have tried your program with a push button on pin 20 which is connected between the pin and ground.
Also activated the pullup resistor on this pin and it works as expected.
ie in first case interrupt is generated when push button is pressed and in second case the interrupt occurs when the push button is released.
regards
Gerry
Yes, you are right, it is really working! I just have a hardware error here.

Thank you very much.

beyonlo
Posts: 58
Joined: Thu Nov 26, 2015 8:03 pm

Re: RP2040 PIO Pin change to HIGH do not works

Post by beyonlo » Mon Mar 28, 2022 6:54 pm

pythoncoder wrote:
Fri Mar 25, 2022 10:09 am
It's perhaps worth pointing out that these examples detect pin changes and pushbuttons usually produce multiple pin changes due to contact bounce. There are better ways of handling pushbuttons and switches such as the uasyncio classes documented here.
Hello @pythoncoder

I'm not using a push button, the signal (high/low) come from a digital signal, so, in this case, it do not need a debounce, because the signal is perfect. And, I'm doing a real-time application, so I need to use always with high speed interruption. I will force (run manually) the gc.collect() to run at the moment that I not running a real-time task. Anyway I would like to do a question about that: what happen if an external interruption happen in the exactly moment that the GC are running? Will the GC to stop to answer the external interruption?

Thank you in advance!

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

Re: RP2040 PIO Pin change to HIGH do not works

Post by pythoncoder » Tue Mar 29, 2022 9:34 am

beyonlo wrote:
Mon Mar 28, 2022 6:54 pm
...
I'm not using a push button, the signal (high/low) come from a digital signal, so, in this case, it do not need a debounce, because the signal is perfect. And, I'm doing a real-time application, so I need to use always with high speed interruption. I will force (run manually) the gc.collect() to run at the moment that I not running a real-time task. Anyway I would like to do a question about that: what happen if an external interruption happen in the exactly moment that the GC are running? Will the GC to stop to answer the external interruption?...
Fair point about the signal.

The way an interrupt service routine (ISR) interacts with GC depends on whether the interrupt is defined as hard or soft. If it's hard, it pre-empts the GC. This imposes restrictions on what the ISR can do - see this doc.

Soft ISR's are delayed until any running GC is complete. This can imply significant latency, but allows the ISR to run any Python code.
Peter Hinch
Index to my micropython libraries.

beyonlo
Posts: 58
Joined: Thu Nov 26, 2015 8:03 pm

Re: RP2040 PIO Pin change to HIGH do not works

Post by beyonlo » Tue Mar 29, 2022 9:10 pm

pythoncoder wrote:
Tue Mar 29, 2022 9:34 am
beyonlo wrote:
Mon Mar 28, 2022 6:54 pm
...
I'm not using a push button, the signal (high/low) come from a digital signal, so, in this case, it do not need a debounce, because the signal is perfect. And, I'm doing a real-time application, so I need to use always with high speed interruption. I will force (run manually) the gc.collect() to run at the moment that I not running a real-time task. Anyway I would like to do a question about that: what happen if an external interruption happen in the exactly moment that the GC are running? Will the GC to stop to answer the external interruption?...
Fair point about the signal.

The way an interrupt service routine (ISR) interacts with GC depends on whether the interrupt is defined as hard or soft. If it's hard, it pre-empts the GC. This imposes restrictions on what the ISR can do - see this doc.

Soft ISR's are delayed until any running GC is complete. This can imply significant latency, but allows the ISR to run any Python code.
Hello @pythoncoder

That URL doc is very good, thank you, but I not found answer to these questions:

1. How I know if an interruption is Hard or Soft? For example: the PIO RP2040 example in this thread (pio_pinchange.py) is a hard or soft interruption?
2. About the GC, when GC runs, the main loop will stop until GC finish. But if I'm using the RP2040, where is possible to use simultaneously the two cores, with a independent main loop in each core, the GC will stop the main loop ONLY on the Core0, or will stop the main loop in both cores?
3. I have a curiosity: in a scenario where is not possible to choose a right moment to run the GC manually, I mean, I need real-time tasks forever, is possible to disable the GC? Of course Python need the GC for collect the garbage of free memory from objects. But If I do not use objects like as float, lists, dict, etc, using just objects that will allocate memory once, like as array, integer and so on, is that possible?

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

Re: RP2040 PIO Pin change to HIGH do not works

Post by pythoncoder » Wed Mar 30, 2022 9:47 am

Interrupts are soft by default: see docs.

Each core on the RP2 runs a completely separate instance of MP.

It is possible to disable GC

Code: Select all

>>> import gc
>>> dir(gc)
['__class__', '__name__', 'collect', 'disable', 'enable', 'isenabled', 'mem_alloc', 'mem_free', 'threshold']
>>> 
however it requires great care. It is quite difficult to write code which never allocates, as anyone who has written hard ISR's will have discovered.
Peter Hinch
Index to my micropython libraries.

beyonlo
Posts: 58
Joined: Thu Nov 26, 2015 8:03 pm

Re: RP2040 PIO Pin change to HIGH do not works

Post by beyonlo » Wed Mar 30, 2022 2:19 pm

pythoncoder wrote:
Wed Mar 30, 2022 9:47 am
Interrupts are soft by default: see docs.

Each core on the RP2 runs a completely separate instance of MP.

It is possible to disable GC

Code: Select all

>>> import gc
>>> dir(gc)
['__class__', '__name__', 'collect', 'disable', 'enable', 'isenabled', 'mem_alloc', 'mem_free', 'threshold']
>>> 
however it requires great care. It is quite difficult to write code which never allocates, as anyone who has written hard ISR's will have discovered.
Hello @pythoncoder

All right!

Is correct to say that, even is difficult do write code which never allocates, if I try to avoid to use objects like as lists/dict/float for example, using array/integer as substitute, when I will run manually the gc.collect(), the GC will run faster? Or independent how much memory needs to be released, the time used for the GC is the same?


Edit:

In my very simple test (just a loop doing gc.collect()), I mean, without lists, dicts or floats, the gc.collect() time is ~1926us (~2ms). Is possible to change something to the gc.collect() be faster?

Below my simple test - gc1.py:

Code: Select all

from machine import freq
import gc, time, array
freq(273_000_000)

gc.disable()

time_list = array.array('i', (0 for _ in range(10)))
count = 0

gc.collect()

while count < 10:
    start_time = time.ticks_us()
    gc.collect()
    end_time = time.ticks_us()
    time_list[count] = time.ticks_diff(end_time, start_time)
    count += 1

print(time_list)
print(freq())
Output:

Code: Select all

>>> import os
>>> os.uname()
(sysname='rp2', nodename='rp2', release='1.18.0', version='v1.18 on 2022-01-17 (GNU 11.2.0 MinSizeRel)', machine='Raspberry Pi Pico with RP2040')
>>> 
>>> import gc1
array('i', [1955, 1926, 1926, 1926, 1926, 1926, 1927, 1926, 1926, 1926])
273000000
>>> 
>>> 

Post Reply