RP2040 PIO: Script fails on some GPIO numbers
Port, board and/or hardware
RP Pico (RP2040)
MicroPython version
MicroPython v1.26.1 on 2025-09-11; Raspberry Pi Pico with RP2040
Reproduction
Link GPIO 1-17, attach a scope/LA to GPIO 2, and run the following:
from machine import Pin, PWM
import rp2
import time
inp = Pin(0, Pin.IN)
jmp = Pin(1, Pin.IN)
opp = Pin(2, Pin.OUT, value=1)
pwm = PWM(Pin(17)) # Link GPIO 17 to GPIO 1
pwm.freq(1000)
pwm.duty_u16(0xFFFF // 2)
@rp2.asm_pio(out_init=rp2.PIO.OUT_LOW)
def sm_test():
set(x, 0)
wrap_target()
wait(0, pins, 1) # Wait for GPIO 1 to go low
mov(osr, x) # Ouput==0 while input==0
out(pins, 1)
label("loop") # Loop until jump pin goes high
jmp(pin, "pulse")
jmp("loop")
label("pulse")
mov(osr, invert(x)) # Emit a pulse
out(pins, 1)
mov(osr, x)
out(pins, 1)
wrap()
sm0 = rp2.StateMachine(0, sm_test, freq=100_000, out_base=opp , in_base=inp, jmp_pin=jmp)
sm0.restart()
sm0.active(1)
while True:
time.sleep(1)
print("Running")
Expected behaviour
Expected to output a single pulse on GPIO 2 after every positive going edge of GPIO 17.
Observed behaviour
As written, works as designed.
If the link is changed to link GPIO 17 and 14, and the code changed to read
inp = Pin(13, Pin.IN)
jmp = Pin(14, Pin.IN)
pulses are emitted all the time the input is high. If GPIO 1 is strapped to 3V3, pulses stop. Note GPIO 1 is not referenced in the code.
If GPIO 1 and GPIO 14 are linked it runs as designed. This behaviour continues after a power cycle!
Additional Information
RP2350 behaves similarly except that the sensitivity to GPIO 1 is lacking.
The decorator arg is necessary for the code to work. If this is intended it should be documented as this seems unexpected.
Code of Conduct
Yes, I agree
RP2040, RP2350 PIO: anomalous behaviour of jump pin
Port, board and/or hardware
Pico and Pico 2 (RP2040, RP2350)
MicroPython version
MicroPython v1.26.1 on 2025-09-11; Raspberry Pi Pico with RP2040
RP2350 tests also use release build 1.26.1
Reproduction
Link GPIO 1-17, attach a scope/LA to GPIO 2, and run the following:
from machine import Pin, PWM
import rp2
import time
inp = Pin(0, Pin.IN)
jmp = Pin(1, Pin.IN)
opp = Pin(2, Pin.OUT, value=1)
pwm = PWM(Pin(17)) # Link GPIO 17 to GPIO 1
pwm.freq(1000)
pwm.duty_u16(0xFFFF // 2)
@rp2.asm_pio(out_init=rp2.PIO.OUT_LOW) # Fails to run at all if arg is omitted (RP2040 & RP2350)
def sm_test():
set(x, 0)
wrap_target()
wait(0, pins, 1) # Wait for GPIO 1 to go low
mov(osr, x) # Ouput==0 while input==0
out(pins, 1)
label("loop") # Loop until jump pin goes high
jmp(pin, "pulse")
jmp("loop")
label("pulse")
mov(osr, invert(x)) # Emit a pulse
out(pins, 1)
mov(osr, x)
out(pins, 1)
wrap()
sm0 = rp2.StateMachine(0, sm_test, freq=100_000, out_base=opp , in_base=inp, jmp_pin=jmp)
sm0.restart()
sm0.active(1)
while True:
time.sleep(1)
print("Running")
Expected behaviour
Expected to output a single pulse on GPIO 2 after every positive going edge of GPIO 17.
Observed behaviour
As expected on RP2040. On RP2350 it behaves as if the jump pin were always active with pulses appearing throughout the low period. This behaviour continues if the jump pin is assigned to another GPIO which is strapped low.
On RP2350 and RP2040 if the decorator arg is omitted, no output appears. This seems surprising: if not a bug the requirement should be documented.
Additional Information
No, I've provided everything above.
Code of Conduct
Yes, I agree