rp2: asm_pio_encode() sideset/delay faulty logic
Port, board and/or hardware
RP2040
MicroPython version
MicroPython v1.24.1 on 2024-11-29; Raspberry Pi Pico with RP2040
Reproduction
In a PIO instruction, 5 bits are reserved for sideset/delay. Using one or more sideset pins reduces the amount of bits left for delay. However, the asm_pio_encode() complains about delay too large with the following invocation:
rp2.asm_pio_encode('mov(x,y).side(1) [7]', 2, sideset_opt=True)
The second argument to the function is sideset count and is inclusive of the sideset enable bit which is required when sideset is optional. In this example two bits are reserved for sideset purposes and three are left for delay allowing a maximum of 7.
Expected behaviour
The function is expected to return 48930 equivalent to 0b1011111100100010.
Note the sideset/delay in bits 8-12 (counting up from 0), 11111, with the two most significant bits being the sideset enable and the actual sideset bit and the rest of the bits signifying a delay value of 7.
Observed behaviour
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "rp2.py", line 298, in asm_pio_encode
File "<string>", line 1, in <module>
File "rp2.py", line 79, in getitem
File "rp2.py", line 84, in delay
PIOASMError: delay too large
Additional Information
I came across this bug when figuring out why the asm_pio_encode() function would not seem to work correctly with sideset count equal to 1 while sideset_opt=True.
The documentation did not mention about sideset count being inclusive of sideset enable bit. That information was found in the codebase as a comment. It follows from the SIDESET_COUNT count in SM#_PINCTRL register of RP2040 where the sideset enable bit is included in the count.
Code of Conduct
Yes, I agree
RP2350: PIO scripts fail, despite running on RP2040
Port, board and/or hardware
Pico 2
MicroPython version
MicroPython v1.25.0-preview.408.gf315a376b on 2025-03-26; Raspberry Pi Pico2 with RP2350
Reproduction
It has proved hard to produce a minimum repro, what follows is my best shot. The repro is quite fragile - minimal changes cause its behaviour to vary between working and failing.
Link GPIO numbers 1-18 and 2-17 and run the following:
import rp2
from machine import Pin, SPI
@rp2.asm_pio(autopush=True, autopull=True)
def spi_count():
out(x, 32)
wait(0, pins, 2) # CS/ True
label("loop")
jmp(pin, "good")
jmp(x_dec, "loop")
label("good")
in_(x, 32)
label("finish")
jmp("finish")
class Test:
def __init__(self, start_pin=0, sm_num=0):
self._sm1 = rp2.StateMachine(
sm_num,
spi_count,
in_base=start_pin,
jmp_pin=start_pin + 1,
)
self._sm1.active(1)
def go(self, cs, ck):
sm = self._sm1
sm.put(10_000_000)
cs(0) # Start
ck(1) # Stop
assert sm.rx_fifo(), "Rx fifo is empty."
print(sm.get())
cs = Pin(17, Pin.OUT, value=1)
ck = Pin(18, Pin.OUT, value=0)
t = Test()
t.go(cs, ck)
Expected behaviour
Result on RP2040 is to print a number around 9999759.
Observed behaviour
RP2350 produces an assertion fail. I assume that the RP2350 is failing to respond to the jump pin.
Additional Information
No, I've provided everything above.
Code of Conduct
Yes, I agree