Quantcast
Viewing all articles
Browse latest Browse all 1261

Python • rp2040 DMA Write Register Decrementing?

Having a problem with the DMA writing to a byte memory location one less than the Write Register was set. I have read and write increments off and am transferring only one byte at a time. (string of DMA actions triggered by PIO). Behavior is very intermittent, but I have been able to read the dma write register from the main python loop a few times and actually catch it at a value one less than it was set. Interesting that if I do nothing in the python main (end in loop forever with no statements) the DMA does not have this issue. I have the target board hooked up to a logic analyzer so I can see the fault without software.

I tested at four consecutive addresses thinking this might be related to the 32 bit bus and byte transfer - but every time the bad write is the target address minus one.

The application is intercepting reads and writes on a MC6802 bus. Basically the PIO qualifies the address captures it and pushes out to a string of DMA channels. The DMA manages the read from or write to the bus as required. Writes go from the bus into the rp2 memory and reads out the other way. I compiled a special mircopython to exclude a memory area used for the R/W. The goal was to make the Pico act like a ram device on the bus and use no cor arm resources at all (all pio/dma).

Any ideas welcome and thanks in advance!


# PIO_PRG: Find address match
#
# Memory usage <<8>>
# Sideset used for A_Select
# Input at A10 to gather A10 and A11
# Set base used for LED - diagnostics
#
# note: A10 ans A11 can now be included in the hardware OR
# gate (optionally) which wouls remove the need for this
# part of the PIO program chain
#@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW, sideset_init=rp2.PIO.OUT_LOW)
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW)
def address_match():

label("strt_match_address")
wrap_target()
in_(null,32) .side(0) [4] #clear ISR, set A_Select=0
wait(0, gpio, 13) [2] #PSM [1] #wait for VMA+ADR to go active

#code here will operate in the E clock negative 1/2 cycle
in_(pins, 2) [4] #shift in A11 and A12 for the rest of the address

#check for all 0 (A11 and A12 are low)
mov (x,isr) [4]
jmp (x_dec, "strt_match_address") #if non-zero loop back to top, could add other tests for alternate addresses

#check vma adr.....
jmp(pin,"strt_match_address")
#address qualified now - launch next pio to get the address read
irq(4)
wait(1,irq,6)
wrap()


# PIO_PRG: Generate flash address
#
# MEmeory Usage <<6>>
# (Address in PICO for flash access)
#
#@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW,sideset_init=rp2.PIO.OUT_LOW)
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW)
def address_read():

#upper 21 bits of pico flash address fixed from outside - written to Y
#setup here to read entire 11 bit address
wrap_target()
wait (1,irq,4) [5] #wait for IRQ4 to be set - also will RESET IRQ!!

mov(isr,y) #copy 21 bit address msb to isr,ready to shift in 11 lsb from pins

in_(pins,3) [7] .side(1) #read A8/9/10, set A_Select to 1
nop()[4]
in_(pins,8) .side(0) #read A0-7, set A_Select back to 0

#want to be ~1/8us after VMA here - if eclock is low - go ahead.
push(noblock) # [1] #send out address result for DMA to copy around

irq(5)
wrap()



#PIO_PRG : Data read or write
#
# Memory Usage <<17>>
#
# Set (pins,1) #diag
#
#@rp2.asm_pio (out_init= (rp2.PIO.IN_HIGH,)*8, out_shiftdir=rp2.PIO.SHIFT_RIGHT ,set_init=rp2.PIO.OUT_LOW, sideset_init=rp2.PIO.OUT_LOW )
@rp2.asm_pio (out_init= (rp2.PIO.IN_HIGH,)*8, out_shiftdir=rp2.PIO.SHIFT_RIGHT , sideset_init=rp2.PIO.OUT_LOW )
def rw_data():

wrap_target()
in_(null,32) #clear isr
wait(1,irq,5) #wait for IRQ5 and reset it

mov(osr,x) #preload x now to save time if this is a read
wait(1, gpio, 1) [7] #PSM [3] #wait for eclock to go HIGH

jmp(pin,"do_write") #pin is W/R (inverted!)

#READ PROCESS - send data out to pins
out(pindirs,8) [5] .side(1) #pins to outputs (1=output), #side set is data_dir output
pull() #TX fifo -> OSR
out(pins,8) #OSR -> Pins
jmp("wrap_up")

#WRITE Process - read pins send to sram
label("do_write")
pull(noblock) [7] #pull and discard
in_(pins,8) #read all 8 data in one go
push(noblock) #picked up by DMA6

label("wrap_up")
mov(osr,y) .side(0)
wait(0, gpio, 1) [2] #wait for eclock to go LOW

out(pindirs,8) .side(0) #pins to inputs
#pull(noblock) #pull and discard - should NOT need this.... make sure incomming fifo empty
irq(6) .side(0) #release cycle to start again

wrap()




#125Mhz, (8nS) Max speeds
sm_address_match = rp2.StateMachine(0,address_match,freq=125000000,sideset_base=machine.Pin(27), in_base=machine.Pin(9),jmp_pin=machine.Pin(13),set_base=machine.Pin(26))
sm_address_read = rp2.StateMachine(1,address_read, freq=100000000,sideset_base=machine.Pin(27), in_base=machine.Pin(6),jmp_pin=machine.Pin(13),set_base=machine.Pin(26))
sm_read_write = rp2.StateMachine(2, rw_data, freq=125000000,out_base=machine.Pin(14), in_base=machine.Pin(14),jmp_pin=machine.Pin(12),set_base=machine.Pin(26), sideset_base=machine.Pin(28))

sm_address_match.active(1) #Start PIO0_0
#clear IRQs that PIO 0 will use for clean start up
sm_address_match.exec("irq(clear,4)")
sm_address_match.exec("irq(clear,5)")
sm_address_match.exec("irq(clear,6)")

sm_address_read.active(1) #Start PIO0_1
#preload shadow ram address into y:
sm_address_read.put(RamDef.SRAM_DATA_BASE_21)
sm_address_read.exec("pull()")
sm_address_read.exec("out(y,32)")

sm_read_write.active(1) #Start PIO0_2
#preload ZERO into Y for use as pindirs for data lines
sm_read_write.put(0x000)
sm_read_write.exec("pull()")
sm_read_write.exec("out(y,8)")
#preload ONES into X for use as pindirs for data lines
sm_read_write.put(0x0FF )
sm_read_write.exec("pull()")
sm_read_write.exec("out(x,8)")

#**************************************************
# DMA Setup for bus memory access, read and writes
#**************************************************

a=rp2.DMA()
b=rp2.DMA()
c=rp2.DMA()
d=rp2.DMA()
e=rp2.DMA()
f=rp2.DMA()
print (a,b,c,d,e,f)

#DMA channel assignments
DMA_ADDRESS_MATCH = 2 # 0->2
DMA_ADDRESS_COPY = 3 # 1->3
DMA_READ = 4
#5 empty
DMA_WRITE = 6
DMA_WRITE_RETRIG = 7

#uctypes structs for each channel
dma_address_match = dma_d.DMA_CHANS[DMA_ADDRESS_MATCH] #2
dma_address_copy1 = dma_d.DMA_CHANS[DMA_ADDRESS_COPY] #3
dma_read = dma_d.DMA_CHANS[DMA_READ] #4
# dma 5 not used
dma_write = dma_d.DMA_CHANS[DMA_WRITE] #6
dma_write_retrig = dma_d.DMA_CHANS[DMA_WRITE_RETRIG] #7

#------------------------
# DMA 2 for address match
#------------------------
dma_address_match.READ_ADDR_REG = 0x50200000 + 0x024 # PIO0_SM1 RX buffer
dma_address_match.WRITE_ADDR_REG = 0x50000000 + 0x13C # DMA4 SRC register - also cause trigger of DMA4!
dma_address_match.CTRL_REG.CHAIN_TO = DMA_ADDRESS_COPY
dma_address_match.CTRL_REG.INCR_WRITE = 0
dma_address_match.CTRL_REG.INCR_READ = 0
dma_address_match.CTRL_REG.IRQ_QUIET = 1
dma_address_match.CTRL_REG.TREQ_SEL = dma_d.DREQ_PIO0_RX1 #wait on PIO0-SM1 RX
dma_address_match.CTRL_REG.DATA_SIZE = 2
dma_address_match.CTRL_REG.EN = 1
dma_address_match.TRANS_COUNT_REG_TRIG = 1 #trigger this DMA (will wait on DREQ)

#-------------------------
# DMA 3 address copy
#-------------------------
dma_address_copy1.READ_ADDR_REG = 0x50000000 + 0x100 # DMA4 SRC register
dma_address_copy1.WRITE_ADDR_REG = 0x50000000 + 0x184 # DMA6 DEST register
dma_address_copy1.TRANS_COUNT_REG = 1
dma_address_copy1.CTRL_REG.CHAIN_TO = DMA_ADDRESS_MATCH #DMA_ADDRESS_RETRIG
dma_address_copy1.CTRL_REG.INCR_WRITE = 0
dma_address_copy1.CTRL_REG.INCR_READ = 0
dma_address_copy1.CTRL_REG.IRQ_QUIET = 1
dma_address_copy1.CTRL_REG.TREQ_SEL = 0x3F
dma_address_copy1.CTRL_REG.DATA_SIZE = 2
dma_address_copy1.CTRL_REG.EN = 1


#-------------------------
# DMA 4 Read Data
#-------------------------
#dma_address_copy1.READ_ADDR_REG = # SRC set to sram location (and trigger) by DMA0
dma_read.WRITE_ADDR_REG = 0x50200000 + 0x0018 # PIO0_SM2 TX FIFO
dma_read.TRANS_COUNT_REG = 1
dma_read.CTRL_REG.CHAIN_TO = DMA_READ # no rettrig req, trigger by src write DMA0, DMA_READ_RETRIG
dma_read.CTRL_REG.INCR_WRITE = 0
dma_read.CTRL_REG.INCR_READ = 0
dma_read.CTRL_REG.HIGH_PRIORITY = 1
dma_read.CTRL_REG.IRQ_QUIET = 1
dma_read.CTRL_REG.TREQ_SEL = 0x3F
dma_read.CTRL_REG.DATA_SIZE = 0 #byte data transfer!
dma_read.CTRL_REG.EN = 1

#----------------------
# DMA 6 for data write
#----------------------
#write data from incomming bus to pico sram
dma_write.READ_ADDR_REG = 0x50200000 + 0x028 # data out of PIO0-SM2 RX (data pio)
dma_write.WRITE_ADDR_REG = 0x20040000 #uctypes.addressof(shadowRam) # written by other dmas to point into sram
dma_write.CTRL_REG.CHAIN_TO = DMA_WRITE_RETRIG
dma_write.CTRL_REG.INCR_WRITE = 0
dma_write.CTRL_REG.INCR_READ = 0
dma_write.CTRL_REG.HIGH_PRIORITY = 1
dma_write.CTRL_REG.IRQ_QUIET = 1
dma_write.CTRL_REG.TREQ_SEL = dma_d.DREQ_PIO0_RX2 #wait for RX outof PIO-SM2
dma_write.CTRL_REG.DATA_SIZE = 0
dma_write.CTRL_REG.EN = 1
dma_write.TRANS_COUNT_REG_TRIG = 1 #trigger this DMA (will wait on DREQ)

#----------------------------
# DMA 7 data write retrigger
#----------------------------
dma_write_retrig.READ_ADDR_REG = 0x50000000 + 0x184 #DMA6 DEST
dma_write_retrig.WRITE_ADDR_REG = 0x2003F080 #0x50300000 + 0x018 #PIO1_SM2 TX
#dma_write_retrig.TRANS_COUNT_REG = 1
dma_write_retrig.CTRL_REG.CHAIN_TO = DMA_WRITE
dma_write_retrig.CTRL_REG.INCR_WRITE = 0
dma_write_retrig.CTRL_REG.INCR_READ = 0
dma_write_retrig.CTRL_REG.IRQ_QUIET = 1
dma_write_retrig.CTRL_REG.TREQ_SEL = 0x3F
dma_write_retrig.CTRL_REG.DATA_SIZE = 2
dma_write_retrig.CTRL_REG.EN = 1
dma_write_retrig.TRANS_COUNT_REG_TRIG = 1





button = machine.Pin(22,Pin.IN)

print("dma control ragisters ",hex(dma_write.CTRL_REG_TRIG)," ",hex(dma_read.CTRL_REG_TRIG))

while True:
#print(" dma6 write adr = ",hex(dma_write.WRITE_ADDR_REG))
print(" ram: ",end="")
for i in range(30):
print(" ",hex(ram_access),end="")
print(" ")

print(" ",hex(dma_write.WRITE_ADDR_REG)," ",hex(dma_read.WRITE_ADDR_REG )," ",hex(ram_access[0x80])," ",hex(ram_access[0x81])," ",hex(ram_access[0x82])," ",hex(ram_access[0x83]))
sleep(0.1)

if button.value()==0 :
for i in range(30):
ram_access=5

Statistics: Posted by PinballCentral — Sat Mar 02, 2024 3:28 pm



Viewing all articles
Browse latest Browse all 1261

Trending Articles