Skip to content

Commit 77dca35

Browse files
committed
docs: Add documentation for rp2 DMA support.
Signed-off-by: Nicko van Someren <nicko@nicko.org>
1 parent 516385c commit 77dca35

File tree

3 files changed

+174
-0
lines changed

3 files changed

+174
-0
lines changed

docs/library/rp2.DMA.rst

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
.. currentmodule:: rp2
2+
.. _rp2.DMA:
3+
4+
class DMA -- access to the RP2040's DMA controller
5+
==================================================
6+
7+
The :class:`DMA` class gives access the channels in the RP2040's Direct Memory Access (DMA)
8+
controller, providing the ability move data between memory blocks and/or IO registers. The DMA
9+
controller has its own, separate read and write master connections onto the bus fabric and each DMA
10+
channel can independently read data from one address and write it back to another address,
11+
optionally incrementing one or both pointers, allowing it to perform transfers on behalf of the
12+
process while the processor carries out other tasks or enters a low power state. The RP2040's DMA
13+
controller has 12 independent DMA channels that can run concurrently. For full details of the
14+
RP2040's DMA system see section 2.5 of the `RP2040 Datasheet
15+
<https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf>`_.
16+
17+
18+
Examples
19+
--------
20+
21+
The simplest use of the DMA controller is to move data from one block of memory to another.
22+
This can be accomplished with the following code::
23+
24+
a = bytearray(32*1024)
25+
b = bytearray(32*1024)
26+
d = rp2.DMA()
27+
c = d.pack_ctrl() # Just use the default control value.
28+
# The count is in transfers, which default to four-byte words, so divide length by 4
29+
d.setup(read=a, write=b, count=len(a)//4, config=c, trigger=True)
30+
# Wait for completion
31+
while d.active:
32+
pass
33+
34+
Note that while this example sits in an idle loop while it waits for the transfer to complete,
35+
the program could just as well do some useful work in this time instead.
36+
37+
Another, perhaps more common use of the DMA controller is to transfer between memory and an IO
38+
peripheral. In this situation the address of the IO register does not change for each transfer but
39+
the memory address needs to be incremented. It is also necessary to control the pace of the
40+
transfer so as to not write data before it can be accepted by a peripheral or read it before the
41+
data is read, and this can be controlled with the ``treq_sel`` field of the DMA channel's control
42+
register. The various fields of the control register for each DMA channel can be packed
43+
using the :meth:`DMA.pack_crtl()` method and unpacked using the :meth:`DMA.unpack_crtl()`
44+
static method. Code to transfer data from a byte array to the TX FIFO of a PIO state machine,
45+
one byte at a time, looks like this::
46+
47+
# pio_num is index of the PIO block being used, sm_num is the state machine in that block.
48+
# my_state_machine is an rp2.PIO() instance.
49+
DATA_REQUEST_INDEX = (pio_num << 3) + sm_num
50+
51+
src_data = bytearray(1024)
52+
d = rp2.DMA()
53+
54+
# Transfer bytes, rather than words, don't increment the write address and pace the transfer.
55+
c = d.pack_ctrl(size=0, inc_write=False, c.treq_sel=DATA_REQUEST_INDEX)
56+
57+
d.setup(
58+
read=src_data,
59+
write=my_state_machine.get_fifo_addr(False), # The address of the write FIFO
60+
count=len(a),
61+
config=c,
62+
trigger=True
63+
)
64+
65+
66+
67+
Constructor
68+
-----------
69+
70+
.. class:: DMA( )
71+
72+
Claim one of the DMA controller channels for exclusive use.
73+
74+
75+
Methods
76+
-------
77+
78+
.. method:: DMA.config(read=None, write=None, count=None, ctrl=None, trigger=False)
79+
80+
Configure the DMA registers for the channel and optionally start the transfer.
81+
82+
:param read: The address from which the DMA controller will start reading data or
83+
an object that will provide data to be read. It can be an integer or any
84+
object that supports the buffer protocol.
85+
:param write: The address to which the DMA controller will start writing or an
86+
object into which data will be written. It can be an integer or any object
87+
that supports the buffer protocol.
88+
:param count: The number of bus transfers that will execute before this channel
89+
stops. Note that this is the number of transfers, not the number of bytes.
90+
If the transfers are 2 or 4 bytes wide then the total amount of data moved
91+
(and thus the size of required buffer) needs to be multiplied accordingly.
92+
:param ctrl: The value for the DMA control register. This is an integer value
93+
that is typically packed using the :meth:`DMA.pack_ctrl()`.
94+
:param trigger: Optionally commence the transfer immediately.
95+
96+
.. method:: DMA.irq(handler=None, hard=False)
97+
98+
Returns the IRQ object for this DMA channel and optionally configures it.
99+
100+
.. method:: DMA.close()
101+
102+
Release the claim on the underlying DMA channel and free the interrupt
103+
handler. The :class:`DMA` object can not be used after this operation.
104+
105+
.. method:: DMA.pack_crtl(default=None, **kwargs)
106+
107+
Pack the values provided in the keyword arguments into the named fields of a new control
108+
register value. Any field that is not provided will be set to a default value. The
109+
default will either be taken from the provided ``default`` value, or if that is not
110+
given, a default suitable for the current channel.
111+
112+
The keys for the keyword arguments can be any key returned by the :meth:`DMA.unpack_crtl()`
113+
method. That method will also return values for the read-only fields in the control register;
114+
these values will be ignored when packing, so that the dictionary created by unpacking a
115+
control register can be used directly as the keyword arguments for packing.
116+
117+
.. method:: DMA.unpack_crtl(value)
118+
119+
Unpack a value for a DMA channel control register into a dictionary with key/value pairs
120+
for each of the fields in the control register.
121+
122+
:param value: The ``crtl`` register value to unpack.
123+
124+
125+
126+
Attributes
127+
----------
128+
129+
.. attribute:: DMA.active
130+
131+
An attribute to get or set whether the DMA channel is currently running.
132+
133+
>>> sm.active
134+
0
135+
>>> sm.active = 1
136+
>>> while sm.active:
137+
... pass
138+
139+
.. attribute:: DMA.read
140+
141+
This attribute reflects the address from which the next bus transfer
142+
will read. May be written with either an integer or an object
143+
that supports the buffer protocol and doing so has immediate effect.
144+
145+
.. attribute:: DMA.write
146+
147+
This attribute reflects the address to which the next bus transfer
148+
will write. May be written with either an integer or an object
149+
that supports the buffer protocol and doing so has immediate effect.
150+
151+
.. attribute:: DMA.count
152+
153+
Reading this attribute will return the number of remaining bus
154+
transfers in the *current* transfer sequence. Writing this attribute
155+
sets the total number of transfers to be the *next* transfer sequence.
156+
157+
.. attribute:: DMA.ctrl
158+
159+
This attribute reflects DMA channel control register. It is typicall written
160+
with an integer packed using the :meth:`DMA.pack_crtl()` method. The returned
161+
register value can be unpacked using the :meth:`DMA.unpack_crtl()` method.
162+
163+
.. attribute:: DMA.channel_id
164+
165+
The channel number of the DMA channel.
166+
167+
.. attribute:: DMA.registers
168+
169+
This attribute is an array-like object that allows direct access to
170+
the DMA channel's registers. The index is by word, rather than by byte,
171+
so the register indicies are the register address offsets divided by 4.
172+
See the RP2040 data sheet for register details.

docs/library/rp2.StateMachine.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,4 @@ Methods
140140

141141
Optionally configure it.
142142

143+
.. method:: StateMachine.get_fifo_proxy(read_not_write)

docs/library/rp2.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,4 @@ Classes
244244
rp2.Flash.rst
245245
rp2.PIO.rst
246246
rp2.StateMachine.rst
247+
rp2.DMA.rst

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy