DMA, adresses
-
- Posts: 14
- Joined: Sat Jan 30, 2021 11:18 pm
Re: DMA, adresses
Very nice, thanks for sharing!
Re: DMA, adresses [Solved]
Two things: Once again I was chatched by the fact, that one cannot redefine a const. so I changed the setting in creating the TRIG_CTRL patter outside the DMAStart function and supply it as an argument. Looks like:
The other problem catches me now for a while: I cannot set more than 8 pins at once in a PIO script. Whatever I do, it sticks to <=8. Has anyone a clue why? The code below works fine, consuming 16 bit patterns, but the 9th bit is not set. The lower 8 bits show up right. It seems that this 9th bit is not set to output mode.
Edit: It looks like a pin direction init problem. If I enable in the PIO code the pindirs, by setting the first words of my data appropriately, it works fine. So the out_init= is not processed rigth, or I am missing something. The PIO code the looks like:
Code: Select all
RQ_QUIET = (0x1) # do not generate an interrupt
TREQ_SEL = (0x00) # wait for PIO0_TX0
CHAIN_TO = (0) # do not chain
RING_SEL = (0)
RING_SIZE = (0) # no wrapping
INCR_WRITE = (0) # for write to array
INCR_READ = (1) # for read from array
DATA_SIZE = (0) # 8-bit word transfer
HIGH_PRIORITY = (1)
EN = (1)
DMA_stream_control = ((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))
@micropython.viper
def DMA_start(chan:uint, ar, nword:uint, control:uint):
dma=ptr32(uint(DMA_BASE) + chan * 0x40)
dma[READ_ADDR] = uint(ptr32(ar))
dma[WRITE_ADDR] = uint(PIO0_BASE_TXF0)
dma[TRANS_COUNT] = nword
dma[CTRL_TRIG] = control
Code: Select all
@rp2.asm_pio(
sideset_init=(rp2.PIO.OUT_HIGH,) * 2,
out_init=(rp2.PIO.OUT_HIGH,) * 9,
out_shiftdir=rp2.PIO.SHIFT_RIGHT,
autopull=True,
pull_thresh=16)
def data9_write():
# fmt: off
out(pins, 9) .side(0b10)
out(null, 7) .side(0b11)
# fmt: on
Code: Select all
@rp2.asm_pio(
sideset_init=(rp2.PIO.OUT_HIGH,) * 2,
out_init=(rp2.PIO.OUT_HIGH,) * 9,
out_shiftdir=rp2.PIO.SHIFT_RIGHT,
autopull=True,
pull_thresh=16)
def data9_write():
# fmt: off
out(pindirs, 9) .side(0b00)
out(null, 7) .side(0b00)
wrap_target()
out(pins, 9) .side(0b10)
out(null, 7) .side(0b11)
wrap()
# fmt: on
Re: DMA, adresses
For anyone who might be interested in a REPL friendly way to interact with the DMA module, I wrote a uctypes wrapper
https://github.com/hoihu/projects/blob/ ... ico/dma.py
example (memcopy of 2 bytearrays):
https://github.com/hoihu/projects/blob/ ... ransfer.py
Note that this might not be as performant as the other proposals, but I found it helpful while using the REPL (since the register names come up with tab completition etc).
https://github.com/hoihu/projects/blob/ ... ico/dma.py
example (memcopy of 2 bytearrays):
https://github.com/hoihu/projects/blob/ ... ransfer.py
Note that this might not be as performant as the other proposals, but I found it helpful while using the REPL (since the register names come up with tab completition etc).
Re: DMA, adresses
some snippets on how to glue the PIO configured for ws2812 (Neopixel) with the DMA controller can be found here:
https://github.com/hoihu/projects/blob/ ... _ws2812.py
basically all it does is to setup a dma channel to push out the data to the PIO's TXFIFO. The configuration of the PIO is the same as on the existing official example (pio_ws2812.py). I only tested it with my logic analyser.
Some notes / thought..
I guess what would be nice is to use a second DMA channel channel that reconfigures the first one, once it has finished the transfer (as detailed in the chapter 2.5.6.2. DMA Control Blocks). This would allow to continuously stream/update the framebuffers data to the Neopixels in the background... imagine a neopixel screen. Not sure though about the necessary 50usec reset in between the refresh cycles.... Perhaps using an IRQ at the end of the transfer is simpler to handle (?)
A blocker to stream the framebuffer data out is also the missing support of RGB888 mode... This would have been a good match for the 8 bit wide neopixel colors.
https://github.com/hoihu/projects/blob/ ... _ws2812.py
basically all it does is to setup a dma channel to push out the data to the PIO's TXFIFO. The configuration of the PIO is the same as on the existing official example (pio_ws2812.py). I only tested it with my logic analyser.
Some notes / thought..
I guess what would be nice is to use a second DMA channel channel that reconfigures the first one, once it has finished the transfer (as detailed in the chapter 2.5.6.2. DMA Control Blocks). This would allow to continuously stream/update the framebuffers data to the Neopixels in the background... imagine a neopixel screen. Not sure though about the necessary 50usec reset in between the refresh cycles.... Perhaps using an IRQ at the end of the transfer is simpler to handle (?)
A blocker to stream the framebuffer data out is also the missing support of RGB888 mode... This would have been a good match for the 8 bit wide neopixel colors.