Page 1 of 2
RP2040 PIO Pin change to HIGH do not works
Posted: Tue Mar 22, 2022 1:27 am
by beyonlo
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!
Re: RP2040 PIO Pin change to HIGH do not works
Posted: Wed Mar 23, 2022 9:31 pm
by beyonlo
I still have no success, could anyone help me?
Thank you.
Re: RP2040 PIO Pin change to HIGH do not works
Posted: Thu Mar 24, 2022 4:43 pm
by GerryKeely
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
Re: RP2040 PIO Pin change to HIGH do not works
Posted: Fri Mar 25, 2022 10:09 am
by pythoncoder
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.
Re: RP2040 PIO Pin change to HIGH do not works
Posted: Mon Mar 28, 2022 6:43 pm
by beyonlo
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.
Re: RP2040 PIO Pin change to HIGH do not works
Posted: Mon Mar 28, 2022 6:54 pm
by beyonlo
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!
Re: RP2040 PIO Pin change to HIGH do not works
Posted: Tue Mar 29, 2022 9:34 am
by pythoncoder
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.
Re: RP2040 PIO Pin change to HIGH do not works
Posted: Tue Mar 29, 2022 9:10 pm
by beyonlo
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?
Re: RP2040 PIO Pin change to HIGH do not works
Posted: Wed Mar 30, 2022 9:47 am
by pythoncoder
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.
Re: RP2040 PIO Pin change to HIGH do not works
Posted: Wed Mar 30, 2022 2:19 pm
by beyonlo
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
>>>
>>>