8000 docs/rp2: Add reference for PIO assembly instructions, and PIO tutorial. · micropython/micropython@baa5a76 · GitHub
[go: up one dir, main page]

Skip to content

Commit baa5a76

Browse files
NitiKaurdpgeorge
authored andcommitted
docs/rp2: Add reference for PIO assembly instructions, and PIO tutorial.
1 parent d42cba0 commit baa5a76

File tree

3 files changed

+280
-0
lines changed

3 files changed

+280
-0
lines changed

docs/library/rp2.rst

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,158 @@ For running PIO programs, see :class:`rp2.StateMachine`.
7272
an error assembling a PIO program.
7373

7474

75+
PIO assembly language instructions
76+
----------------------------------
77+
78+
PIO state machines are programmed in a custom assembly language with nine core
79+
PIO-machine instructions. In MicroPython, PIO assembly routines are written as
80+
a Python function with the decorator ``@rp2.asm_pio()``, and they use Python
81+
syntax. Such routines support standard Python variables and arithmetic, as well
82+
as the following custom functions that encode PIO instructions and direct the
83+
assembler. See sec 3.4 of the RP2040 datasheet for further details.
84+
85+
wrap_target()
86+
Specify the location where execution continues after program wrapping.
87+
By default this is the start of the PIO routine.
88+
89+
wrap()
90+
Specify the location where the program finishes and wraps around.
91+
If this directive is not used then it is added automatically at the end of
92+
the PIO routine. Wrapping does not cost any execution cycles.
93+
94+
label(label)
95+
Define a label called *label* at the current location. *label* can be a
96+
string or integer.
97+
98+
word(instr, label=None)
99+
Insert an arbitrary 16-bit word in the assembled output.
100+
101+
- *instr*: the 16-bit value
102+
- *label*: if given, look up the label and logical-or the label's value with
103+
*instr*
104+
105+
jmp(...)
106+
This instruction takes two forms:
107+
108+
jmp(label)
109+
- *label*: label to jump to unconditionally
110+
111+
jmp(cond, label)
112+
- *cond*: the condition to check, one of:
113+
114+
- ``not_x``, ``not_y``: true if register is zero
115+
- ``x_dec``, ``y_dec``: true if register is non-zero, and do post
116+
decrement
117+
- ``x_not_y``: true if X is not equal to Y
118+
- ``pin``: true if the input pin is set
119+
- ``not_osre``: true if OSR is not empty (hasn't reached its
120+
threshold)
121+
122+
- *label*: label to jump to if condition is true
123+
124+
wait(polarity, src, index)
125+
Block, waiting for high/low on a pin or IRQ line.
126+
127+
- *polarity*: 0 or 1, whether to wait for a low or high value
128+
- *src*: one of: ``gpio`` (absolute pin), ``pin`` (pin relative to
129+
StateMachine's ``in_base`` argument), ``irq``
130+
- *index*: 0-31, the index for *src*
131+
132+
in_(src, bit_count)
133+
Shift data in from *src* to ISR.
134+
135+
- *src*: one of: ``pins``, ``x``, ``y``, ``null``, ``isr``, ``osr``
136+
- *bit_count*: number of bits to shift in (1-32)
137+
138+
out(dest, bit_count)
139+
Shift data out from OSR to *dest*.
140+
141+
- *dest*: one of: ``pins``, ``x``, ``y``, ``pindirs``, ``pc``, ``isr``,
142+
``exec``
143+
- *bit_count*: number of bits to shift out (1-32)
144+
145+
push(...)
146+
Push ISR to the RX FIFO, then clear ISR to zero.
147+
This instruction takes the following forms:
148+
149+
- push()
150+
- push(block)
151+
- push(noblock)
152+
- push(iffull)
153+
- push(iffull, block)
154+
- push(iffull, noblock)
155+
156+
If ``block`` is used then the instruction stalls if the RX FIFO is full.
157+
The default is to block. If ``iffull`` is used then it only pushes if the
158+
input shift count has reached its threshold.
159+
160+
pull(...)
161+
Pull from the TX FIFO into OSR.
162+
This instruction takes the following forms:
163+
164+
- pull()
165+
- pull(block)
166+
- pull(noblock)
167+
- pull(ifempty)
168+
- pull(ifempty, block)
169+
- pull(ifempty, noblock)
170+
171+
If ``block`` is used then the instruction stalls if the TX FIFO is empty.
172+
The default is to block. If ``ifempty`` is used then it only pulls if the
173+
output shift count has reached its threshold.
174+
175+
mov(dest, src)
176+
Move into *dest* the value from *src*.
177+
178+
- *dest*: one of: ``pins``, ``x``, ``y``, ``exec``, ``pc``, ``isr``, ``osr``
179+
- *src*: one of: ``pins``, ``x``, ``y``, ``null``, ``status``, ``isr``,
180+
``osr``; this argument can be optionally modified by wrapping it in
181+
``invert()`` or ``reverse()`` (but not both together)
182+
183+
irq(...)
184+
Set or clear an IRQ flag.
185+
This instruction takes two forms:
186+
187+
irq(index)
188+
- *index*: 0-7, or ``rel(0)`` to ``rel(7)``
189+
190+
irq(mode, index)
191+
- *mode*: one of: ``block``, ``clear``
192+
- *index*: 0-7, or ``rel(0)`` to ``rel(7)``
193+
194+
If ``block`` is used then the instruction stalls until the flag is cleared
195+
by another entity. If ``clear`` is used then the flag is cleared instead of
196+
being set. Relative IRQ indices add the state machine ID to the IRQ index
197+
with modulo-4 addition. IRQs 0-3 are visible from to the processor, 4-7 are
198+
internal to the state machines.
199+
200+
set(dest, data)
201+
Set *dest* with the value *data*.
202+
203+
- *dest*: ``pins``, ``x``, ``y``, ``pindirs``
204+
- *data*: value (0-31)
205+
206+
nop()
207+
This is a pseudoinstruction that assembles to ``mov(y, y)`` and has no side
208+
effect.
209+
210+
.side(value)
211+
This is a modifier which can be applied to any instruction, and is used to
212+
control side-set pin values.
213+
214+
- *value*: the value (bits) to output on the side-set pins
215+
216+
.delay(value)
217+
This is a modifier which can be applied to any instruction, and specifies
218+
how many cycles to delay for after the instruction executes.
219+
220+
- *value*: cycles to delay, 0-31 (maximum value reduced if side-set pins are
221+
used)
222+
223+
[value]
224+
This is a modifier and is equivalent to ``.delay(value)``.
225+
226+
75227
Classes
76228
-------
77229

docs/rp2/tutorial/intro.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,8 @@ Getting started with MicroPython on the RP2xxx
44
==============================================
55

66
Let's get started!
7+
8+
.. toctree::
9+
:maxdepth: 1
10+
11+
pio.rst

docs/rp2/tutorial/pio.rst

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
Programmable IO
2+
===============
3+
4+
The RP2040 has hardware support for standard communication protocols like I2C,
5+
SPI and UART. For protocols where there is no hardware support, or where there
6+
is a requirement of custom I/O behaviour, Programmable Input Output (PIO) comes
7+
into play. Also, some MicroPython applications make use of a technique called
8+
bit banging in which pins are rapidly turned on and off to transmit data. This
9+
can make the entire process slow as the processor concentrates on bit banging
10+
rather than executing other logic. However, PIO allows bit banging to happen
11+
in the background while the CPU is executing the main work.
12+
13+
Along with the two central Cortex-M0+ processing cores, the RP2040 has two PIO
14+
blocks each of which has four independent state machines. These state machines
15+
can transfer data to/from other entities using First-In-First-Out (FIFO) buffers,
16+
which allow the state machine and main processor to work indepen 10000 dently yet also
17+
synchronise their data. Each FIFO has four words (each of 32 bits) which can be
18+
linked to the DMA to transfer larger amounts of data.
19+
20+
All PIO instructions follow a common pattern::
21+
22+
<instruction> .side(<side_set_value>) [<delay_value>]
23+
24+
The side-set ``.side(...)`` and delay ``[...]`` parts are both optional, and if
25+
specified allow the instruction to perform more than one operation. This keeps
26+
PIO programs small and efficient.
27+
28+
There are nine instructions which perform the following tasks:
29+
30+
- ``jmp()`` transfers control to a different part of the code
31+
- ``wait()`` pauses until a particular action happens
32+
- ``in_()`` shifts the bits from a source (scratch register or set of pins) to the
33+
input shift register
34+
- ``out()`` shifts the bits from the output shift register to a destination
35+
- ``push()`` sends data to the RX FIFO
36+
- ``pull()`` receives data from the TX FIFO
37+
- ``mov()`` moves data from a source to a destination
38+
- ``irq()`` sets or clears an IRQ flag
39+
- ``set()`` writes a literal value to a destination
40+
41+
The instruction modifiers are:
42+
43+
- ``.side()`` sets the side-set pins at the start of the instruction
44+
- ``[]`` delays for a certain number of cycles after execution of the instruction
45+
46+
There are also directives:
47+
48+
- ``wrap_target()`` specifies where the program execution will get continued from
49+
- ``wrap()`` specifies the instruction where the control flow of the program will
50+
get wrapped from
51+
- ``label()`` sets a label for use with ``jmp()`` instructions
52+
- ``word()`` emits a raw 16-bit value which acts as an instruction in the program
53+
54+
An example
55+
----------
56+
57+
Take the ``pio_1hz.py`` example for a simple understanding of how to use the PIO
58+
and state machines. Below is the code for reference.
59+
60+
.. code-block:: python3
61+
62+
# Example using PIO to blink an LED and raise an IRQ at 1Hz.
63+
64+
import time
65+
from machine import Pin
66+
import rp2
67+
68+
69+
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
70+
def blink_1hz():
71+
# Cycles: 1 + 1 + 6 + 32 * (30 + 1) = 1000
72+
irq(rel(0))
73+
set(pins, 1)
74+
set(x, 31) [5]
75+
label("delay_high")
76+
nop() [29]
77+
jmp(x_dec, "delay_high")
78+
79+
# Cycles: 1 + 7 + 32 * (30 + 1) = 1000
80+
set(pins, 0)
81+
set(x, 31) [6]
82+
label("delay_low")
83+
nop() [29]
84+
jmp(x_dec, "delay_low")
85+
86+
87+
# Create the StateMachine with the blink_1hz program, outputting on Pin(25).
88+
sm = rp2.StateMachine(0, blink_1hz, freq=2000, set_base=Pin(25))
89+
90+
# Set the IRQ handler to print the millisecond timestamp.
91+
sm.irq(lambda p: print(time.ticks_ms()))
92+
93+
# Start the StateMachine.
94+
sm.active(1)
95+
96+
This creates an instance of class :class:`rp2.StateMachine` which runs the
97+
``blink_1hz`` program at 2000Hz, and connects to pin 25. The ``blink_1hz``
98+
program uses the PIO to blink an LED connected to this pin at 1Hz, and also
99+
raises an IRQ as the LED turns on. This IRQ then calls the ``lambda`` function
100+
which prints out a millisecond timestamp.
101+
102+
The ``blink_1hz`` program is a PIO assembler routine. It connects to a single
103+
pin which is configured as an output and starts out low. The instructions do
104+
the following:
105+
106+
- ``irq(rel(0))`` raises the IRQ associated with the state machine.
107+
- The LED is turned on via the ``set(pins, 1)`` instruction.
108+
- The value 31 is put into register X, and then there is a delay for 5 more
109+
cycles, specified by the ``[5]``.
110+
- The ``nop() [29]`` instruction waits for 30 cycles.
111+
- The ``jmp(x_dec, "delay_high")`` will keep looping to the ``delay_high`` label
112+
as long as the register X is non-zero, and will also post-decrement X. Since
113+
X starts with the value 31 this jump will happen 31 times, so the ``nop() [29]``
114+
runs 32 times in total (note there is also one instruction cycle taken by the
115+
``jmp`` for each of these 32 loops).
116+
- ``set(pins, 0)`` will turn the LED off by setting pin 25 low.
117+
- Another 32 loops of ``nop() [29]`` and ``jmp(...)`` will execute.
118+
- Because ``wrap_target()`` and ``wrap()`` are not specified, their default will
119+
be used and execution of the program will wrap around from the bottom to the
120+
top. This wrapping does not cost any execution cycles.
121+
122+
The entire routine takes exactly 2000 cycles of the state machine. Setting the
123+
frequency of the state machine to 2000Hz makes the LED blink at 1Hz.

0 commit comments

Comments
 (0)
0