I been running code very similar to the channel_irq.c example on git, but I using micropython. But there is no output when I use this code on pico 2, although it works as intended on pico (no 2). The idea is to stream an array values bitwise across 8 GPIO pins using a PIO and DMA, when the buffer runs out a second DMA resets the first (that what is similar to the channel_irq.c example). I created this by modifying an example of creating a function generator with just PIO connected to GPIO and resisters (I wish I remember), it sent a array of byte to the PIO to be output to GPIO bins and the resister network created a voltage, the array defined a sine wave (for example). I just want the a binary pattern generator with 8 channels, so I have no resisters, but the idea is the same.
I think it must be something simple, due to my general ignorance. There is no output at all.
I cannot figure out what is wrong, or find any examples that of using DMA with PIO for pico 2 that are verified to work.
Did something change with pico 2. Can anyone point me to an example that does work (of using the DMA to feed data for the PIO to stream to GPIO pins). I include most of the source below, but please be aware it is not mine originally (I only changed it a little bit).
#constant for access to DMA and PIO
DMA_BASE=0x50000000
CH0_READ_ADDR =DMA_BASE+0x000
CH0_WRITE_ADDR =DMA_BASE+0x004
CH0_TRANS_COUNT=DMA_BASE+0x008
CH0_CTRL_TRIG =DMA_BASE+0x00c
CH0_AL1_CTRL =DMA_BASE+0x010
CH1_READ_ADDR =DMA_BASE+0x040
CH1_WRITE_ADDR =DMA_BASE+0x044
CH1_TRANS_COUNT=DMA_BASE+0x048
CH1_CTRL_TRIG =DMA_BASE+0x04c
CH1_AL1_CTRL =DMA_BASE+0x050
CHAN_ABORT =DMA_BASE+0x444
PIO0_BASE =0x50200000
PIO0_BASE_TXF0 =PIO0_BASE+0x10
#PIO1_BASE = 0x50300000
#The state machine is very simple
#describe a state machine that just pushes bytes to the pins (from the DMA)
@asm_pio(out_init=(PIO.OUT_HIGH,PIO.OUT_HIGH,PIO.OUT_HIGH,PIO.OUT_HIGH,PIO.OUT_HIGH,PIO.OUT_HIGH,PIO.OUT_HIGH,PIO.OUT_HIGH), out_shiftdir=PIO.SHIFT_RIGHT, autopull=True, pull_thresh=32)
def stream():
out(pins,8)
#create the state machine
sm = StateMachine(0, stream, freq=sm_clock, out_base=Pin(0))
sm.active(0)
print('PIOs progammed')
sm.active(1)
print('PIOs started')
#At this point you create a byte array and fill it with values, you also create num_elements to store the number of elements in the array, which is divisible by 4.
#code not shown
#Then program the DMA, the DMA is working 4 bytes at a time, which gives time to reset it.
@micropython.viper
def startDMA(ar,nword):
print('programming dma')
#halt/reset DMA channel 0 and 1
mem32[CHAN_ABORT]=3
p=ptr32(ar)
mem32[CH0_READ_ADDR]=p
mem32[CH0_WRITE_ADDR]=PIO0_BASE_TXF0
mem32[CH0_TRANS_COUNT]=nword
IRQ_QUIET=0x1 #do not generate an interrupt
TREQ_SEL=0x00 #wait for PIO0_TX0
CHAIN_TO=1 #start channel 1 when done
RING_SEL=0
RING_SIZE=0 #no wrapping
INCR_WRITE=0 #for write to array
INCR_READ=1 #for read from array
DATA_SIZE=2 #32-bit word transfer
HIGH_PRIORITY=1
EN=1
CTRL0=(IRQ_QUIET<<21)|(TREQ_SEL<<15)|(CHAIN_TO<<11)|(RING_SEL<<10)|(RING_SIZE<<9)|(INCR_WRITE<<5)|(INCR_READ<<4)|(DATA_SIZE<<2)|(HIGH_PRIORITY<<1)|(EN<<0)
mem32[CH0_AL1_CTRL]=CTRL0
#setup second DMA which reconfigures the first channel
p_ar[0]=p
mem32[CH1_READ_ADDR]=ptr(p_ar)
mem32[CH1_WRITE_ADDR]=CH0_READ_ADDR
mem32[CH1_TRANS_COUNT]=1
IRQ_QUIET=0x1 #do not generate an interrupt
TREQ_SEL=0x3f #no pacing
CHAIN_TO=0 #start channel 0 when done
RING_SEL=0
RING_SIZE=0 #no wrapping
INCR_WRITE=0 #single write
INCR_READ=0 #single read
DATA_SIZE=2 #32-bit word transfer
HIGH_PRIORITY=1
EN=1
CTRL1=(IRQ_QUIET<<21)|(TREQ_SEL<<15)|(CHAIN_TO<<11)|(RING_SEL<<10)|(RING_SIZE<<9)|(INCR_WRITE<<5)|(INCR_READ<<4)|(DATA_SIZE<<2)|(HIGH_PRIORITY<<1)|(EN<<0)
mem32[CH1_CTRL_TRIG]=CTRL1
print('dma started')
#start DMA
DMA_elements=floor(num_elements/4)
startDMA(bufferArray,floor(num_elements/4))
#At this point the program can just halt and the PIO and DMA continue to work until the are stopped.
I think it must be something simple, due to my general ignorance. There is no output at all.
I cannot figure out what is wrong, or find any examples that of using DMA with PIO for pico 2 that are verified to work.
Did something change with pico 2. Can anyone point me to an example that does work (of using the DMA to feed data for the PIO to stream to GPIO pins). I include most of the source below, but please be aware it is not mine originally (I only changed it a little bit).
#constant for access to DMA and PIO
DMA_BASE=0x50000000
CH0_READ_ADDR =DMA_BASE+0x000
CH0_WRITE_ADDR =DMA_BASE+0x004
CH0_TRANS_COUNT=DMA_BASE+0x008
CH0_CTRL_TRIG =DMA_BASE+0x00c
CH0_AL1_CTRL =DMA_BASE+0x010
CH1_READ_ADDR =DMA_BASE+0x040
CH1_WRITE_ADDR =DMA_BASE+0x044
CH1_TRANS_COUNT=DMA_BASE+0x048
CH1_CTRL_TRIG =DMA_BASE+0x04c
CH1_AL1_CTRL =DMA_BASE+0x050
CHAN_ABORT =DMA_BASE+0x444
PIO0_BASE =0x50200000
PIO0_BASE_TXF0 =PIO0_BASE+0x10
#PIO1_BASE = 0x50300000
#The state machine is very simple
#describe a state machine that just pushes bytes to the pins (from the DMA)
@asm_pio(out_init=(PIO.OUT_HIGH,PIO.OUT_HIGH,PIO.OUT_HIGH,PIO.OUT_HIGH,PIO.OUT_HIGH,PIO.OUT_HIGH,PIO.OUT_HIGH,PIO.OUT_HIGH), out_shiftdir=PIO.SHIFT_RIGHT, autopull=True, pull_thresh=32)
def stream():
out(pins,8)
#create the state machine
sm = StateMachine(0, stream, freq=sm_clock, out_base=Pin(0))
sm.active(0)
print('PIOs progammed')
sm.active(1)
print('PIOs started')
#At this point you create a byte array and fill it with values, you also create num_elements to store the number of elements in the array, which is divisible by 4.
#code not shown
#Then program the DMA, the DMA is working 4 bytes at a time, which gives time to reset it.
@micropython.viper
def startDMA(ar,nword):
print('programming dma')
#halt/reset DMA channel 0 and 1
mem32[CHAN_ABORT]=3
p=ptr32(ar)
mem32[CH0_READ_ADDR]=p
mem32[CH0_WRITE_ADDR]=PIO0_BASE_TXF0
mem32[CH0_TRANS_COUNT]=nword
IRQ_QUIET=0x1 #do not generate an interrupt
TREQ_SEL=0x00 #wait for PIO0_TX0
CHAIN_TO=1 #start channel 1 when done
RING_SEL=0
RING_SIZE=0 #no wrapping
INCR_WRITE=0 #for write to array
INCR_READ=1 #for read from array
DATA_SIZE=2 #32-bit word transfer
HIGH_PRIORITY=1
EN=1
CTRL0=(IRQ_QUIET<<21)|(TREQ_SEL<<15)|(CHAIN_TO<<11)|(RING_SEL<<10)|(RING_SIZE<<9)|(INCR_WRITE<<5)|(INCR_READ<<4)|(DATA_SIZE<<2)|(HIGH_PRIORITY<<1)|(EN<<0)
mem32[CH0_AL1_CTRL]=CTRL0
#setup second DMA which reconfigures the first channel
p_ar[0]=p
mem32[CH1_READ_ADDR]=ptr(p_ar)
mem32[CH1_WRITE_ADDR]=CH0_READ_ADDR
mem32[CH1_TRANS_COUNT]=1
IRQ_QUIET=0x1 #do not generate an interrupt
TREQ_SEL=0x3f #no pacing
CHAIN_TO=0 #start channel 0 when done
RING_SEL=0
RING_SIZE=0 #no wrapping
INCR_WRITE=0 #single write
INCR_READ=0 #single read
DATA_SIZE=2 #32-bit word transfer
HIGH_PRIORITY=1
EN=1
CTRL1=(IRQ_QUIET<<21)|(TREQ_SEL<<15)|(CHAIN_TO<<11)|(RING_SEL<<10)|(RING_SIZE<<9)|(INCR_WRITE<<5)|(INCR_READ<<4)|(DATA_SIZE<<2)|(HIGH_PRIORITY<<1)|(EN<<0)
mem32[CH1_CTRL_TRIG]=CTRL1
print('dma started')
#start DMA
DMA_elements=floor(num_elements/4)
startDMA(bufferArray,floor(num_elements/4))
#At this point the program can just halt and the PIO and DMA continue to work until the are stopped.
Statistics: Posted by dmhueber — Mon Jan 06, 2025 3:14 pm — Replies 0 — Views 2