rp2: No Pin IRQ on core 1 (on core 0: OK)
Port, board and/or hardware
RP2, PICO and PICO2, RP2040 and RP2350
MicroPython version
MicroPython v1.26.0 on 2025-08-09; Raspberry Pi Pico2 with RP2350
No Pin() IRQ when using the second core (_thread).
Primary core works as intended.
Reproduction
#!micropython
# -*- coding: UTF-8 -*-
# vim:fileencoding=UTF-8:ts=4
#╭──────────────────────────────────────────────────────────────────────────────╮
#│ PICO_THREAD_PIN_IRQ_TEST.PY │
#│ Board: PICO2/RP2350 │
#│ Micropython: 3.4.0; MicroPython v1.26.0 on 2025-08-09 │
#│ Testing: Pin.irq() on both cores │
#│ using a bridge between GPIO16 and GPIO17 │
#│ GPIO16 runs a slow PWM │
#│ GPIO17 acts as an input with IRQ │
#╰──────────────────────────────────────────────────────────────────────────────╯
import _thread
from sys import version
from array import array
from machine import Pin, PWM
from time import sleep_ms
_SIO_BASE = const(0xd0000000)
_CPUID = const(0x000 >>2)
_THREAD_HLT = const(0)
_THREAD_RUN = const(1)
_THREAD_FIN = const(2)
@micropython.viper
def cpuid() -> int:
sio: ptr32 = ptr32(_SIO_BASE)
return sio[_CPUID]
def core1(data,hard):
def cb_core1(pin):
print('cb_core1(): IRQ on core:', cpuid(), end=' ')
print('count:', data[1])
if data[1]:
data[1] -= 1
print('core1() is running on core:', cpuid())
pin = Pin(17, Pin.IN, Pin.PULL_UP)
data[1] = 5
pin.irq(handler=cb_core1, trigger=Pin.IRQ_FALLING, hard=hard)
while data[0] == _THREAD_RUN and data[1]:
sleep_ms(10)
pin.irq(None)
pin.init()
data[0] = _THREAD_FIN
return
def core0():
def cb_core0(pin):
print('cb_core0(): IRQ on core:', cpuid(), end=' ')
print('count:', data[1])
if data[1]:
data[1] -= 1
print(version)
data = array('I', (_THREAD_HLT,0)) # [0]state [1] counter
pwm = PWM(16, freq=10, duty_u16=2**15)
print('Testing hard=False on core 0')
pin = Pin(17, Pin.IN, None)
data[1] = 5
pin.irq(handler=cb_core0, trigger=Pin.IRQ_FALLING, hard=False)
while data[1]:
sleep_ms(10)
pin.irq(None)
pin.init()
print('Testing hard=True on core 0')
pin = Pin(17, Pin.IN, None)
data[1] = 5
pin.irq(handler=cb_core0, trigger=Pin.IRQ_FALLING, hard=True)
while data[1]:
sleep_ms(10)
pin.irq(None)
pin.init()
print('Testing hard=False on core 1')
data[0] = _THREAD_RUN
_thread.start_new_thread(core1, (data,False))
loops = 100
while (loops:= loops-1) and data[0] != _THREAD_FIN:
sleep_ms(10)
data[0] = _THREAD_HLT
while data[0] != _THREAD_FIN: pass
print('Testing hard=True on core 1')
data[0] = _THREAD_RUN
_thread.start_new_thread(core1, (data,True))
loops = 100
while (loops:= loops-1) and data[0] != _THREAD_FIN:
sleep_ms(10)
data[0] = _THREAD_HLT
while data[0] != _THREAD_FIN: pass
pwm.deinit()
core0()
3.4.0; MicroPython v1.26.0 on 2025-08-09
Testing hard=False on core 0
cb_core0(): IRQ on core: 0 count: 5
cb_core0(): IRQ on core: 0 count: 4
cb_core0(): IRQ on core: 0 count: 3
cb_core0(): IRQ on core: 0 count: 2
cb_core0(): IRQ on core: 0 count: 1
Testing hard=True on core 0
cb_core0(): IRQ on core: 0 count: 5
cb_core0(): IRQ on core: 0 count: 4
cb_core0(): IRQ on core: 0 count: 3
cb_core0(): IRQ on core: 0 count: 2
cb_core0(): IRQ on core: 0 count: 1
Testing hard=False on core 1
core1() is running on core: 1
Testing hard=True on core 1
core1() is running on core: 1
### Expected behaviour
Well, should fire IRQ/callback events when running on core 1.
### Observed behaviour
Does not.
### Additional Information
No, I've provided everything above.
### Code of Conduct
Yes, I agree
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