Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 4906

MicroPython • Two PIOs for more as 32 instructions

$
0
0
I have a successfully working MDIO PIO interface (in MicroPython), based on oscilloscope waveform.
But it creates some questions, such as:

1. Use two PIOs in order to split the number of instructions (as total of 32 for one PIO, for all 4 SM per PIO):
I have a clock generator SM and a SM to wait for 32 clock cycles (to make sure, each transaction has 32bit clocks before data frame). I was thinking to move this SM code to another PIO (to gain more space for instructions, some SM code is independent of the PIO).

BTW: if you select the sm_id as 4 in MicroPython, it should go to the next PIO1 (sm_id 0..3 = PIO0 SM, sm_id 4..7 = PIO1 SM).
And it seems to do so: now I have not the OOMEM error anymore when moving code to another PIO. But moving SM code to another PIO does not work (in a simple way).

It is NOT possible to use IRQ signals between PIO0 and PIO1. Just a GPIO might work. IRQ signals are NOT shared between different PIOs (just inside the 4 SM of the same PIO).
So, running my clock generator (and/or my "wait for 32 clocks" SM) on a different PIO (e.g. PIO1) where the main SM code is on PIO0 - does not work (because "IRQs are not shared").

2. Can PIO0 generate a GPIO signal (OUT) which is an input GPIO (IN) on PIO1?
Due to fact that IRQs do not work across different PIOs - the only way is to use a "shared" GPIO. So, if my clock generator would provide a clock on GPIO0, using PIO1, and I want to WAIT for this same GPIO, as input on PIO0 - would it work?
It means:
Is it possible to generate GPIO0 as OUT on PIO0 and PIO1 uses the same GPIO0 as in IN (for WAIT)?
(or: "which config would win?", if PIO1 configures GPIO0 as IN, but PIO0 wants to use as out - it would fail)

Remarks:
  • the max. 32 instructions (per PIO) is very at the lowest limit. It would be cool to have a bit more space for instructions (in future versions of the RP2350)
  • that the IRQ does not work across several PIOs is a "missing feature" (for my feeling). It would be cool to be able to move some instructions to another PIO (e.g. my clock generator) and to synchronize both PIOs (via IRQ)
  • not sure if possible to use a "shared" GPIO: one PIO generates as OUT and other PIO can use WAIT on the same GPIO (but as IN).
    If so: it would solve "my" problem (PIO1 generates clock, PIO0 uses wait for CLK edges, even without IRQ). Just not sure if possible to have a "shared" GPIO signal this way.
Pretty cool features provided by the PICO PIO. Just a bit unclear on very specific details (e.g. using two PIOs at the same time).
To have means to synchronize PIO0 and PIO1 SMs which each other would be cool.

Here the code for my MDIO implementation:

Code:

import timeimport rp2from machine import Pinimport time#clock generator - free running clock, INTs for rising (read) and falling edge (write)@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW)def clk():    #this results in 25MHz clock    #trim this so that other SM changes bits on falling edge when sending    #it divides freq by 6    wrap_target()    irq(4)[1].side(1)#1    irq(clear, 4)[0]#2    irq(5)[1].side(0)#3    irq(clear, 5)[0]#4    wrap()    @rp2.asm_pio()def pre():    wrap_target()    pull()#5 : just wait for trigger (any value)    set(x, 31)#6    label("preloop")    irq(block, 4)#7    irq(block, 4)#8 : why do we need 2x?, otherwise too short!    jmp(x_dec, "preloop")#9    push(x)#10 : just trigger main() (any value)    wrap()    #generate a 32bit write transaction: 2bit (START) 2bit (CMD) 10bit (ADDR) 2bit (TA) 16bit (DATA write)@rp2.asm_pio(out_shiftdir=0, pull_thresh=32, out_init=rp2.PIO.OUT_LOW, set_init=rp2.PIO.OUT_LOW, sideset_init=rp3.PIO.OUT_LOW)def dataWrite():    wrap_target()    pull()#11        set(x, 32)#12    label("loop")    irq(block, 4)#13    out(pins, 1).side(1)#14    jmp(x_dec, "loop")#15        irq(block, 4)#16    set(pins, 1).side(1)#17    wrap()    #generate a 16bit read transaction: 2bit (START) 2bit (CMD) 10bit (ADDR), 2bit (TA), 16bit (DATA read) - read with rising edge!@rp2.asm_pio(out_shiftdir=0, pull_thresh=14, push_thresh=16, out_init=rp2.PIO.OUT_LOW, set_init=rp2.PIO.OUT_LOW, sideset_init=rp2.PIO.OUT_LOW)def dataRead():    wrap_target()    pull()#18        set(x, 13)#19    label("loop")    irq(block, 4)#20    out(pins, 1)#21    jmp(x_dec, "loop")#22        irq(block, 4)#23        set(pindirs, 0).side(0)#24 : set the OEN signal low (for DIRection control)    irq(block, 4)#25    set(x, 15)#26    irq(block, 5)#27        label("rx")    irq(block, 5)#28    in_(pins, 1)#29    jmp(x_dec, "rx")#30        push()#31    set(pindirs, 1).side(1)#32 - full 32 instructions on PIO0, set OEN signal high    wrap()    FREQ = 25000000#CLK generator SM0sm0 = rp2.StateMachine(0, clk, freq=FREQ * 6, sideset_base=Pin(2))sm0.active(1)#read cycle SM2sm2 = rp2.StateMachine(2, dataRead, out_base=Pin(3), in_base=Pin(3), set_base=Pin(3), sideset_base=Pin(4))sm2.active(1)#write cycle SM1sm1 = rp2.StateMachine(1, dataWrite, out_base=Pin(3), in_base=Pin(3), set_base=Pin(3), sideset_base=Pin(4))sm1.active(1)sm3 = rp2.StateMachine(3, pre)sm3.active(1)        prevR = 0while True:    sm3.put(0)    sm3.get()    sm2.put(0x1A440000)#generate 13bits of frame start, 2bit TA and read 16bit    r = sm2.get()#get the read result    if prevR != r:        prevR = r#print just if changed (otherwise slows down too much)        print(hex(r))    sm3.put(0)    sm3.get()    sm1.put(0x01A44C084)#generate a write, 2bit (START) + 2bit (CMD) + 10bit (ADDR) + 2bit (TA) + 16bit (DATA write)

Statistics: Posted by tjaekel — Mon Aug 26, 2024 1:54 am



Viewing all articles
Browse latest Browse all 4906

Trending Articles