We use some essential cookies to make our website work.

We use optional cookies, as detailed in our cookie policy, to remember your settings and understand how you use our website.

4 posts • Page 1 of 1
matherp
Posts: 460
Joined: Tue May 02, 2017 10:54 am

RP2350: PIO IRQ between different PIO - something odd

Wed Nov 05, 2025 11:25 am

As far as I can see the documentation is clear but appears backwards
PIO0:
irq 1 next 2 compiles to 0xC01A
PIO1:
wait 1 irq prev 2 compiles to 20CA

should work - but it doesn't.

What does work is:
PIO0:
irq 1 prev 2 compiles to 0xc00A
PIO1:
wait 1 irq next 2 compiles to 20DA

This is on a RP2350 where according to the documentation prev on pio0 should refer to PIO2 as should next on PIO1.
What am I missing?

At the moment I can' get an IRQ set on PIO 1 to trigger a wait on PIO0 at all given any combination of prevs and nexts

hippy
Posts: 19831
Joined: Fri Sep 09, 2011 10:34 pm

Re: RP2350: PIO IRQ between different PIO - something odd

Wed Nov 05, 2025 10:26 pm

I think the issue is that, if in PIO 0 you "Trigger IRQ 2 in Next PIO", then, in PIO 1, the Wait needs to be on "its own IRQ 2", not the previous PIO's.

The second version works because "PIO 0 PREV 2" and "PIO 1 NEXT 2" both refer to "IRQ 2 in PIO 2".

This works for me. It uses interrupts to trigger tasks on alternative PIO -

Code: Select all

 .----->| |<-------------------------.
 | | : |
 | print "Master" .----> Wait for IRQ 1 |
 | | | | |
 | Wait 10 seconds | print "Slave" |
 | | | | |
 | Trigger IRQ 1 on NEXT PIO -----' Wait 5 seconds |
 | : | |
 | Wait for IRQ 0 <--------------------- Trigger IRQ 0 on PREV PIO |
 | | | |
 `------' `--------------------------'

Code: Select all

 Trigger 0xC019 Wait 0x20C1
 Wait 0x20C0 Trigger 0xC008

Code: Select all

from rp2 import asm_pio, StateMachine
import time
@asm_pio()
def Master():
 def Irq(CLR, WAIT, MODE, INDEX):
 return 0xC000 | ((CLR & 1) << 6) | ((WAIT & 1) << 5) | \
 ((MODE & 3) << 3) | (INDEX & 7)
 def Wait(POL, SRC, MODE, INDEX):
 return 0x2000 | ((POL & 1) << 7) | ((SRC & 3) << 5) | \
 ((MODE & 3) << 3) | (INDEX & 7)
 # Get the time delay
 pull(block)
 mov(x, osr)
 label("loop")
 # Indicate activation
 push()
 # Do the delay
 mov(y, x)
 label("delay")
 jmp(y_dec, "delay")
 # Trigger the Slave - Set IRQ 1 in next PIO
 n = Irq(CLR=0, WAIT=0, MODE=0b11, INDEX=1)
 print("Trigger Slave = 0x{:04X}".format(n,))
 word(n)
 # Wait for the Slave complete - Wait until IRQ 0 set, clear IRQ 0
 n = Wait(POL=1, SRC=0b10, MODE=0, INDEX=0)
 print("Wait for Slave = 0x{:04X}".format(n))
 word(n)
 # And repeat forever
 jmp("loop")
@asm_pio()
def Slave():
 def Irq(CLR, WAIT, MODE, INDEX):
 return 0xC000 | ((CLR & 1) << 6) | ((WAIT & 1) << 5) | \
 ((MODE & 3) << 3) | (INDEX & 7)
 def Wait(POL, SRC, MODE, INDEX):
 return 0x2000 | ((POL & 1) << 7) | ((SRC & 3) << 5) | \
 ((MODE & 3) << 3) | (INDEX & 7)
 # Get the time delay
 pull(block)
 mov(x, osr)
 label("loop")
 # Wait to be triggered by Master - Wait until IRQ 1 becomes 1, clear IRQ 1
 n = Wait(POL=1, SRC=0b10, MODE=0, INDEX=1)
 print("Wait for Master = 0x{:04X}".format(n))
 word(n)
 # Indicate activation
 push()
 # Do the delay
 mov(y, x)
 label("delay")
 jmp(y_dec, "delay")
 # Trigger the Master - Set IRQ 0 in previous PIO
 n = Irq(CLR=0, WAIT=0, MODE=0b01, INDEX=0)
 print("Trigger Master = 0x{:04X}".format(n))
 word(n)
 # And repeat forever
 jmp("loop")
# Allocate State Machines
SM_MASTER = 0 # PIO 0
SM_SLAVE = 4 # PIO 1
# Validity checks
print("")
if SM_MASTER < 0 or SM_MASTER > 11:
 print("No such PIO{} for Master on SM{}".format(SM_MASTER >> 2, SM_MASTER))
elif SM_SLAVE < 0 or SM_SLAVE > 11:
 print("No such PIO{} for Slave on SM{}".format(SM_SLAVE >> 2, SM_SLAVE))
elif SM_MASTER >> 2 == SM_SLAVE >> 2:
 print("Master SM{} and Slave SM{} are on the same PIO engine".format(
 SM_MASTER, SM_SLAVE))
else:
 PIO_HZ = 1_000_000
 ONE_SECOND = 1_000_000
 master = StateMachine(SM_MASTER, Master, freq=PIO_HZ)
 master.active(1)
 slave = StateMachine(SM_SLAVE, Slave, freq=PIO_HZ)
 slave.active(1)
 master.put(10 * ONE_SECOND)
 slave.put( 5 * ONE_SECOND)
 # Report when State Machines activate
 NOW = time.time
 was = NOW()
 while True:
 while master.rx_fifo() > 0:
 now = NOW()
 master.get()
 print("{} +{:<3} Master".format(now, now - was))
 was = now
 while slave.rx_fifo() > 0:
 now = NOW()
 slave.get()
 print("{} +{:<3} Slave".format(now, now - was))
 if now == was:
 print("Needs a hard reset")
 was = now

Code: Select all

pi@Pi4B:~/pico/micropython/ports/picopython/modules-examples $ mptool run RP235X_CrossPioIrqTriggers.py
Running './RP235X_CrossPioIrqTriggers.py' on the device
Trigger Slave = 0xC019
Wait for Slave = 0x20C0
Trigger Slave = 0xC019
Wait for Slave = 0x20C0
Wait for Master = 0x20C1
Trigger Master = 0xC008
Wait for Master = 0x20C1
Trigger Master = 0xC008
1609460230 +0 Master
1609460240 +10 Slave
1609460245 +5 Master
1609460255 +10 Slave
1609460260 +5 Master
1609460270 +10 Slave
^C

matherp
Posts: 460
Joined: Tue May 02, 2017 10:54 am

gmx
Posts: 1845
Joined: Thu Aug 29, 2024 8:51 pm

Re: RP2350: PIO IRQ between different PIO - something odd

Thu Nov 06, 2025 3:02 pm

Yep, each PIO block has its own set of IRQ flags.
To communicate between blocks, both should use the same set, not necessarily owned any of them but the same set, not crossed like pipelines.

PIO0 NEXT <=> PIO1
PIO1 NEXT <=> PIO2
PIO2 NEXT <=> PIO0 (wrapping to PIO0 if this is the highest-numbered PIO)

PIO0 PREV <=> PIO2 (wrapping to the highest-numbered PIO if this is PIO0)
PIO1 PREV <=> PIO0
PIO2 PREV <=> PIO1

And then combinations like this:
PIO0 NEXT <=> PIO1 <=> PIO2 PREV
PIO1 NEXT <=> PIO2 <=> PIO0 PREV
PIO2 NEXT <=> PIO0 <=> PIO1 PREV

I hope I didn't mess anything. :)

4 posts • Page 1 of 1

Return to "SDK"

AltStyle によって変換されたページ (->オリジナル) /