PIO: where am I going wrong? [SOLVED-ish]

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
danjperron
Posts: 51
Joined: Thu Dec 27, 2018 11:38 pm
Location: Québec, Canada

Re: PIO: where am I going wrong? [SOLVED-ish]

Post by danjperron » Wed Feb 24, 2021 2:21 pm

One thing I'm unclear about is DMA. When you write to the TX, are you writing to a 4-word FIFO or a DMA buffer that feeds it?
I'm not sure that DMA is used there. I though that is build inside the peripheral since there is no memory involve but just register,
In My DHT22 code I specified the bit threshold to be 8 then the fifo is push after 8 bits with the _in command.
Normal push and pull are 32 bits.

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

Re: PIO: where am I going wrong? [SOLVED-ish]

Post by Roberthh » Wed Feb 24, 2021 7:48 pm

According to my trials, you can configure DMA to write 8, 16 or 32 bytes quantities.

danjperron
Posts: 51
Joined: Thu Dec 27, 2018 11:38 pm
Location: Québec, Canada

Re: PIO: where am I going wrong? [SOLVED-ish]

Post by danjperron » Wed Feb 24, 2021 8:02 pm

I think the IRQ feature could be used to achieve this.
And yes! Your sample code using IRQ. The 200ms sleep act like the timeout.

Code: Select all

from machine import Pin, Timer
from rp2 import PIO, StateMachine, asm_pio
import time

Counter = 0
gotCounter = False

def smIrqHandler(sm):
    global Counter
    global gotCounter
    _counter = sm.get()
    if not gotCounter:
        Counter  = 1 + ( _counter ^ 0xffffffff)  # 2's complement
        gotCounter = True

@rp2.asm_pio(set_init=rp2.PIO.IN_LOW, autopush=True, push_thresh=32)
def mark():
    wrap_target()
    set(x, 0)
    wait(0, pin, 0)  # Wait for pin to go low
    wait(1, pin, 0)  # Low to high transition
    label('low_high')
    jmp(x_dec, 'next')  # unconditional
    label('next')
    jmp(pin, 'low_high')  # while pin is high
    in_(x, 32)  # Auto push: SM stalls if FIFO full
    irq(0)
    wrap()

pin16 = Pin(16, Pin.IN, Pin.PULL_UP)
sm0 = rp2.StateMachine(0, mark, in_base=pin16, jmp_pin=pin16)
sm0.irq(smIrqHandler)
sm0.active(1)

#pin17 = Pin(17, Pin.OUT)
#tim = Timer(freq=1000, mode=Timer.PERIODIC, callback=lambda _: pin17(not pin17(                                                                                                                                                             )))

maxval = 0
minval = 1000_000
while True:
    if gotCounter:
        a = Counter
        maxval = max(maxval, a)
        minval = min(minval, a)
        print(a, maxval, minval)
        gotCounter=False
    else:
        print(0)
    time.sleep_ms(200)

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Firmware bug

Post by dhylands » Wed Feb 24, 2021 8:50 pm

pythoncoder wrote:
Wed Feb 24, 2021 6:14 am
Secondly the timer pulse durations vary, occasionally quite radically. But it can take quite a few single shot readings to spot this. Maybe it's only certain types of busy work which affect the timer?
The only thing that should cause the pulse durations to vary is if a higher priority IRQ is happening. Perhaps a systick timer?

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

Re: Firmware bug

Post by pythoncoder » Thu Feb 25, 2021 5:55 am

dhylands wrote:
Wed Feb 24, 2021 8:50 pm
pythoncoder wrote:
Wed Feb 24, 2021 6:14 am
Secondly the timer pulse durations vary, occasionally quite radically. But it can take quite a few single shot readings to spot this. Maybe it's only certain types of busy work which affect the timer?
The only thing that should cause the pulse durations to vary is if a higher priority IRQ is happening. Perhaps a systick timer?
I think there is something more fundamental going on here with hard interrupts. See this issue. And the script in this thread eventually stopped producing output without actually crashing. A higher priority IRQ could cause variation but shouldn't kill the code.

Re DMA, I hadn't spotted this thread which discusses it at length. As I understand it, both from reading this and from tests, issuing sm.put() writes to the FIFO directly and will block for the duration if you send more data than will fit. So the options for nonblocking are either to code the DMA or to use IRQ's. DMA has the potential to be extremely fast but IRQ's might be easier to code for slower data streams.
Peter Hinch
Index to my micropython libraries.

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

Timer IRQ issue

Post by pythoncoder » Thu Feb 25, 2021 6:13 am

@marfis I have raised this issue with a link to your measurement.
Peter Hinch
Index to my micropython libraries.

sgall17
Posts: 8
Joined: Sun Jan 31, 2021 9:55 pm

Re: PIO: where am I going wrong? [SOLVED-ish]

Post by sgall17 » Tue Aug 17, 2021 6:59 am

The following clip is very basic but as far as I can see is giving the wrong result. Where am I going wrong?

I wanted to implement a tachometer but decrementing X until a pin went HIGH. I thought I could get the X value out by just moving X into ISR then pushing it. As below:.....

Code: Select all

import rp2

code]@rp2.asm_pio()
def prog():
   # set(x,63)
    mov(isr,x)
    push()


sm = rp2.StateMachine(0, prog, freq=4000)
sm.active(1)

for a in range(50):
    sm.exec("set(x,%s)" % a)
    print (sm.get())
    
sm.active(0)

The result is as below:

0
1
2
...

29
30
31
0
1
...
10
11
12

It seems that only the 5 least significant digits are being returned?
What I have done wrong?

Post Reply