From 1e0ac8e29fe4e24ec0e3facd4d5b9f48d1b65b07 Mon Sep 17 00:00:00 2001 From: jimmy Date: Tue, 19 Dec 2023 10:55:14 +0000 Subject: [PATCH] Add dma.py --- dma.py | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 dma.py diff --git a/dma.py b/dma.py new file mode 100644 index 0000000..95ab17d --- /dev/null +++ b/dma.py @@ -0,0 +1,63 @@ +import uctypes +from uctypes import BF_POS, BF_LEN, BFUINT32 + +DMA_CTRL_REG = { + "AHB_ERROR": 31 << BF_POS | 1 << BF_LEN | BFUINT32, + "READ_ERR": 30 << BF_POS | 1 << BF_LEN | BFUINT32, + "WRITE_ERR": 29 << BF_POS | 1 << BF_LEN | BFUINT32, + "Reserved": 25 << BF_POS | 4 << BF_LEN | BFUINT32, + "BUSY": 24 << BF_POS | 1 << BF_LEN | BFUINT32, + "SNIFF_EN": 23 << BF_POS | 1 << BF_LEN | BFUINT32, + "BSWAP": 22 << BF_POS | 1 << BF_LEN | BFUINT32, + "IRQ_QUIET": 21 << BF_POS | 1 << BF_LEN | BFUINT32, + "TREQ_SEL": 15 << BF_POS | 6 << BF_LEN | BFUINT32, + "CHAIN_TO": 11 << BF_POS | 4 << BF_LEN | BFUINT32, + "RING_SEL": 10 << BF_POS | 1 << BF_LEN | BFUINT32, + "RING_SIZE": 6 << BF_POS | 4 << BF_LEN | BFUINT32, + "INCR_WRITE": 5 << BF_POS | 1 << BF_LEN | BFUINT32, + "INCR_READ": 4 << BF_POS | 1 << BF_LEN | BFUINT32, + "DATA_SIZE": 2 << BF_POS | 2 << BF_LEN | BFUINT32, + "HIGH_PRIO": 1 << BF_POS | 1 << BF_LEN | BFUINT32, + "EN": 0 << BF_POS | 1 << BF_LEN | BFUINT32, +} + +DMA_LAYOUT = { + "READ_ADDR": 0 | uctypes.UINT32, + "WRITE_ADDR": 4 | uctypes.UINT32, + "TRANS_COUNT": 8 | uctypes.UINT32, + "CTRL_TRIG": (12, DMA_CTRL_REG), + "CTRL_TRIG_RAW": 12 | uctypes.UINT32, # for single update of all fields + "AL1_CTRL": 16 | uctypes.UINT32, +} + +# create the DMA channel structs (0-11) +CHANNELS = [uctypes.struct(0x50000000 + i * 0x40, DMA_LAYOUT) for i in range(0,12)] + +# init dma channels to some default values +def init_channels(): + for i, ch in enumerate(CHANNELS): + # no wraparound, sniff=0, swap_byte=0, irq_quiet=1 + # unpaced transfers (=0x3f). high prio=0, data_size=word, incr_r/w = true + ch.CTRL_TRIG_RAW = 0x3f8030 + # set chain to itself, to disable chaining + ch.CTRL_TRIG.CHAIN_TO = i + +# example function to show mem->mem transfer +# dest, src can be bytearrays, size in bytes +def memcopy(ch, dest, src, size, enable=1): + ch.CTRL_TRIG.EN = 0 + ch.WRITE_ADDR = uctypes.addressof(dest) + ch.READ_ADDR = uctypes.addressof(src) + ch.TRANS_COUNT = size // (1 << ch.CTRL_TRIG.DATA_SIZE) + ch.CTRL_TRIG.EN = enable + + +# can be used to temporary construct the necessary DMA CTRL values +# then copy over to actual dma channel's CTRL value in one write +# e.g. +# scratch.CHAIN_TO=2; +# scratch.DATA_SIZE=2; +# ... +# CH0.CTRL_TRIG_RAW=scratch.CTRL_TRIG_RAW +tmp = bytearray(uctypes.sizeof(DMA_LAYOUT)) +scratch_ctrl = uctypes.struct(uctypes.addressof(tmp), DMA_CTRL_REG)