← index #8866Issue #11797
Related · medium · value 1.124
QUERY · ISSUE

rp2.StateMachine: state machine fails when I2S protocol is used

openby miketeachmanopened 2022-07-05updated 2022-07-08
bugport-rp2

A rp2 state machine instance can be made to fail when the I2S protocol is used.

Minimal test to reproduce
The code below uses a PIO state machine to flash the onboard LED on a Raspberry Pi Pico development board.

  • Working case: Onboard LED will flash for STATEMACHINE_INSTANCE = 1...7
  • Failure case: Onboard LED will NOT flash for STATEMACHINE_INSTANCE = 0 (shows the Issue)
import time
from machine import Pin, I2S
import rp2

STATEMACHINE_INSTANCE = 0

@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def prog():
    pass

sm = rp2.StateMachine(STATEMACHINE_INSTANCE, prog, set_base=Pin(25))
i2s = I2S(0, sck=Pin(16), ws=Pin(17), sd=Pin(18), mode=I2S.TX, bits=16, format=I2S.STEREO, rate=22_050, ibuf=10000)

while True:
	sm.exec("set(pins, 1)")
	time.sleep(0.5)
	sm.exec("set(pins, 0)")
	time.sleep(0.5)

In the failure case (STATEMACHINE_INSTANCE = 0) , both the rp2.StateMachine instance and the machine.I2S instance try to use state machine 0. Because I2S instantiation follows the rp2.StateMachine instantiation, the state machine configuration used by rp2.StateMachine is overwritten by I2S initialization. This causes a failure in the rp2.StateMachine instance (LED does not flash).

The root cause of this Issue seems to emerge from the rp2.StateMachine implementation. rp2.StateMachine does not make use of the functions for cooperative claiming of hardware that are provided by the Pico SDK. e.g. pio_sm_is_claimed(), pio_sm_unclaim(), pio_claim_unused_sm(). This does not allow any other MicroPython entities (such as I2S) to detect state machine configuration conflicts.

Suggestions for a fix to rp2.StateMachine implementation:
Enhance the rp2.StateMachine implementation to use the Pico SDK functions for cooperative claiming of PIO hardware. The I2S class implementation shows one way to use these functions, in the functions pio_configure() and pio_deinit().

CANDIDATE · ISSUE

rp2 PIO: two statemachines cannot share the same pins if they run on differenit PIOs

closedby makis-mopened 2023-06-16updated 2023-06-17
bug

Hello
I spotted the following issue:
When trying to run two different programs in two statemachines sharing the same pin(s), they work fine ONLY if both statemachines belong to the same PIO (0 or 1), eg one in PIO(0) statemachine 0 and the other in PIO(0) statemachine 1.
The situation changes if the two programs are in different PIOs (one in 0 and the other in 1)
(micropython 1.20 nightly built June 15 2023)
test code:

import time
import rp2
from machine import Pin

@rp2.asm_pio(set_init=(rp2.PIO.OUT_LOW))
def prog_0():
set(pins, 1) [31]
nop() [31]
nop() [31]
nop() [31]
set(pins, 0) [31]
nop() [31]
nop() [31]
nop() [31]
irq(0)

@rp2.asm_pio(set_init=(rp2.PIO.OUT_LOW))
def prog_1():
set(pins, 1) [31]
nop() [31]
nop() [31]
nop() [31]
nop() [31]
nop() [31]
nop() [31]
set(pins, 0) [31]
nop() [31]
nop() [31]
nop() [31]
nop() [31]
nop() [31]
nop() [31]
irq(1)

def irq_handler_0(pio):
print('pio_0', pio.irq().flags())

def irq_handler_1(pio):
print('pio_1', pio.irq().flags())

pio_0 = rp2.PIO(0)
pio_0.irq(irq_handler_0)
pio_1 = rp2.PIO(1)
pio_1.irq(irq_handler_1)

sm0 = pio_0.state_machine(0, prog_0, freq=2000, set_base=Pin(7))
sm1 = pio_1.state_machine(1, prog_1, freq=2000, set_base=Pin(7))

sm0.active(1)
sm1.active(1)
time.sleep(3)
sm0.active(0)
sm1.active(0)

In the above code, the interrupts are working fine (from both programs), so both programs are running, but the led does not respond to instructions of the FIRST assigned statemachine (sm0)
The situation is the same, even if I never activate the second statemachine (sm1): the led does not blink at all (by sm0).
If sm1 is in the same PIO, that is if I change the line
sm1 = pio_1.state_machine(1, prog_1, freq=2000, set_base=Pin(7))
to
sm1 = pio_0.state_machine(1, prog_1, freq=2000, set_base=Pin(7))
everything works fine
The need of having programs running in different PIOs is that you can have more memory (32 instructions per PIO).

Thanks in advance

Keyboard

j / / n
next pair
k / / p
previous pair
1 / / h
show query pane
2 / / l
show candidate pane
c
copy suggested comment
r
toggle reasoning
g i
go to index
?
show this help
esc
close overlays

press ? or esc to close

copied