PIO to DMA with wrapping, is there a way to use the 'ring_size' parameter ? #17129
-
Hello everyone !Rapidly for the context :
For a simplified exemple :the wrap parameters is 8 bits, the mask is then 0x00FF for a little bit of reference : https://docs.micropython.org/en/latest/library/rp2.DMA.html My question is:is there a way to allocate an uarray, that start at a specified memory address ? (in that simplified example it could be 0x0100, or 0x0200, don’t care) And if it’s possible… what addresses range is authorized in micropython on the pi pico ? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
No, there isn't. One has to allocate twice the memory, do some math to determine the offset and then use that offset address. On the Python side setting up a memoryview from offset to offset+size will give you a smaller array within the bigger one. |
Beta Was this translation helpful? Give feedback.
-
Thanks to @GitHubsSilverBullet it’s working \o/. For reference, i’m posting the little bit of code that allowed me to have an array with the correct memory allocation that allowed the DMA to wrap correctly with my array : # SIZE_TRANSFERT : 0 to 2 , 0 : one byte (8bits) , 1: two bytes, on half-word (16bits) , 2: one word (32bits)
# SIZE_BITS_ARRAY : max value of SIZE_BITS_ARRAY + SIZE_TRANSFERT =15
# SIZE_ARRAY : SIZE_ARRAY = 1 << SIZE_BITS_ARRAY ## size of the array in number of element, same as 2**SIZE_BITS_DMA .
cnt = memoryview(uarray.array('L',(0 for _ in range(SIZE_DMA*2)))) # memory reservation of twice the size needed , array of words 'L' (32bits)
address0 = uctypes.addressof(cnt) # address of cnt
#calculate the offset to get the right address to wrap with ring_size=SIZE_BITS_ARRAY +SIZE_TRANSFERT
address_ofset = int((((1 << (SIZE_BITS_ARRAY +SIZE_TRANSFERT ))-1)-(address0 & ((1 << (SIZE_BITS_ARRAY +SIZE_TRANSFERT ))-1) )+1)/int(2**SIZE_TRANSFERT))
dst = memoryview(cnt[address_ofset:address_ofset+SIZE_ARRAY ]) # final array for the DMA config : DREQ_PIO0_RX0 = const(4)
#─────[ Prepare state machine ]────────────────────────────────────
sm0 = StateMachine(0,pio_count,freq=4000) # will count
#─────[ Prepare Chained DMAs for PIO to memory transfer ]────────────────────────────────
dma1 = DMA()
dma2 = DMA()
dma2.active(False)
dma1.active(False)
dma1_ctrl = dma1.pack_ctrl(inc_read=False, inc_write=True, size=SIZE_TRANSFERT , treq_sel=DREQ_PIO0_RX0,irq_quiet=False,chain_to=dma2.channel,ring_size=(SIZE_BITS_ARRAY +SIZE_WORD),ring_sel=True)
dma2_ctrl = dma1.pack_ctrl(inc_read=True, inc_write=True, size=SIZE_TRANSFERT , treq_sel=DREQ_PIO0_RX0,irq_quiet=True,chain_to=dma1.channel,ring_size=(SIZE_BITS_ARRAY +SIZE_WORD),ring_sel=True)
dma1.config(read=sm0, write=dst, count=SIZE_ARRAY , ctrl=dma1_ctrl)
dma2.config(read=sm0, write=dst, count=SIZE_ARRAY , ctrl=dma2_ctrl)
#─────[ Start DMA and State Machine ]──────────────────────────────────────
dma1.active(True)
sm0.active(True) It’s probably not the neater way, but a way that is doing the job, so good enough ;). |
Beta Was this translation helpful? Give feedback.
No, there isn't. One has to allocate twice the memory, do some math to determine the offset and then use that offset address. On the Python side setting up a memoryview from offset to offset+size will give you a smaller array within the bigger one.