8000 RP2 - PIO module by NitiKaur · Pull Request #7496 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content

RP2 - PIO module #7496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3c0781b
brief overwiew with explaination of each command
NitiKaur Jul 6, 2021
d0a38b6
changed self to set instruction
NitiKaur Jul 13, 2021
e49eafe
IRQ instruction updated as per review
NitiKaur Jul 13, 2021
45b666a
all asm PIo instructions moved to new location(docs/library/rp2.rst )…
NitiKaur Jul 13, 2021
8b0e238
asm PIO instructions moved to new location (2)
NitiKaur Jul 13, 2021
b25ea04
typos corrected
NitiKaur Jul 14, 2021
218d0d8
brief description of all instructions added
NitiKaur Jul 14, 2021
1d761a6
blink_1hz example added
NitiKaur Jul 15, 2021
541ab4a
heading added
NitiKaur Jul 17, 2021
b182b08
uppercase to lowercase changes made where necessary
NitiKaur Jul 17, 2021
5ba4a96
typos corrected
NitiKaur Jul 17, 2021
8dce437
Update rp2.rst
NitiKaur Jul 17, 2021
7abf0e7
pio_1hz blink example added
NitiKaur Jul 17, 2021
fc8084d
file location changed
NitiKaur Jul 17, 2021
2a78748
nop instruction added
NitiKaur Jul 17, 2021
cd85f4a
lines wrapped
NitiKaur Jul 17, 2021
08fb1ea
nop syntax added
NitiKaur Jul 18, 2021
286eab1
instructions shifted to lowercase
NitiKaur Jul 18, 2021
c72b933
meta-instructions added
NitiKaur Jul 18, 2021
ab3f11e
IRQ instruction form corrected
NitiKaur Jul 18, 2021
b25d26d
jump instruction syntax corrected
NitiKaur Jul 18, 2021
8a05b83
push instruction forms corrected
NitiKaur Jul 18, 2021
5dcfbd0
pull instruction syntax corrected
NitiKaur Jul 18, 2021
65c1f7d
files corrected
NitiKaur Jul 19, 2021
52b9371
typos corrected
NitiKaur Jul 19, 2021
b76453a
directives,label, delay, side-set added
NitiKaur Jul 25, 2021
f830f4c
set instruction added
NitiKaur Jul 25, 2021
753cb43
typos corrected
NitiKaur Sep 1, 2021
708da6b
typos corrected(2)
NitiKaur Sep 1, 2021
565f65f
typos (3)
NitiKaur Sep 1, 2021
469f318
docs build corrected
NitiKaur Sep 1, 2021
641b949
Merge branch 'master' into rp2_pio
NitiKaur Sep 7, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/library/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,4 @@ The main exception is the port-specific libraries (``pyb``, ``esp``, etc).

*Other than when you specifically want to force the use of the built-in module,
we recommend always using ``import module`` rather than ``import umodule``.*

84 changes: 84 additions & 0 deletions docs/library/rp2.rst
10000
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,90 @@ For running PIO programs, see :class:`rp2.StateMachine`.
This exception is raised from `asm_pio()` or `asm_pio_encode()` if there is
an error assembling a PIO program.

PIO Assembly Language instructions
-----------------------------------

Each state machine has a set of instructions, which allow for a wide range of
behaviourial or location changes to the data. They are written in assembly
language which is later used in a MicroPython program to perform specific
tasks. These instructions are -

jmp(cond, label=None)
This can take two forms:

jmp(label)
label : label to jump to unconditionally

jmp(cond,label)
cond: not_x, x_dec, not_y, y_dec, x_not_y, pin, not_osre
label: label to jump to if condition is true

see sec 3.4.2 of RPi docs for details

wait(polarity, src, index)
polarity: 0-1
src: gpio, pin, irq
index: 0-31
wait for high/low on pin 0-31 or irq 0-31
see sec 3.4.3 of RPi docs for details

in(src, data)
src : pin, x, y, isr, osr(all 0-31)
data : bit count(0-31)
see sec 3.4.4 of RPi docs for details

out(dest,data)
dest : pin, x, y, pindirs, ac, isr, osr(all 0-31)
data : bit count(0-31)
see sec 3.4.5 of RPi docs for details

push()
This instruction takes the following forms:
push()
push(block)
push(noblock)
push(iffull)
push(iffull, block)
push(iffull, noblock)
see sec 3.4.6 of RPi docs for details

pull()
This instruction can take the following forms:
pull()
pull(block)
pull(noblock)
pull(ifempty)
pull(ifempty, block)
pull(ifempty, noblock)
see sec 3.4.7 of RPi docs for details

mov(dest, src)
dest : pin, x, y, isr, osr, pc (all 0-31)
src : pin, x, y, isr, osr (all 0-31)
see sec 3.4.8 of RPi docs for details

set(dest, data)
dest : x, y, pins, pindirs
data : value (0-31)
see sec 3.4.10 of RPi docs for details

irq(mod, index = None)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of this line, I'd suggest breaking this instruction into 2 parts:

irq(index)
     index: <integer> or rel(<integer>)

irq(mode, index)
    mode: block, clear, block|clear
    index: <integer> or rel(<integer>)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or it might be clearer to just write out all 7 possible options explicitly, as done below

These are the following forms of this instruction(index is an integer value
from 0-7)

These can be summarised as two forms:
* form 1: irq(index)
* form 2: irq(mode,index)

where
* index can be an integer or rel(integer)
* mode can be: block or clear or block | clear

Allowed IRQ numbers are 0-7 (0-3 are visible from to the processor, 4-7 are internal to the state machines). See sec 3.4.9 of RPi docs for details

nop(self)
see sec 3.3.7 of RPi docs for details


Classes
-------
Expand Down
123 changes: 123 additions & 0 deletions docs/rp2/tutorial/pio.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
.. _rp2_pio:

RP2040 has standard hardware support like I2C, SPI and UART for communication
protocols with standard devices. For devices where we do not have hardware
support for such protocols or where there is a requirement of more I/O
channels, PIO(Programmable Input Output) comes into play. Also, typical
micropython devices make use of a technique called bit banging in which pins
are rapidly turned on and off to transmit data. This makes the entire process
very slow as the processor concentrates on bit banging rather than excecuting
any other process. However, PIO allows it to carry on with the bit banging
process while the processor resources are used for executing some other work.

Along with the two main cortex - MO+ processing cores, RP2040 has two PIO
blocks each of which has four state machines. These state machines take
process data in FIFO (First-In-First-Out) format. When these state machines
are free, they will put in data from the queue and execute the instruction.
This way, the PIO state machines and the main process works simultaneously
without being much dependent on the other.

Each FIFO has four words (each of 32 bits) which can be linked to the DMA to
transmit larger amounts of data to the PIO state machine and allows it to
carry on execution without the main program keeping a track of it at each
instant of time.

All pioasm instructions follow a common pattern:
<instruction> (side <side_set_value>) ([<delay_value>])

The state machines have 9 instructions which can perform the following tasks:

* IN : shifts the bits from a source (scratch register or set of pins) to the
* input shift register.

* OUT : shifts the bits from the output shift register to a destination

* PUSH : sends data to RX FIFO

* PULL : receives data from TX FIFO

* MOV : moves data from a source to a destination

* IRQ : sets or clears the input flag

* WAIT : pauses until a particular action happens

* JMP : moves to some target locations in different parts of code

* SET : writes data at destination

Apart from the PIO assembly instructions we have the following:

<side_set_value> : value applied to the side set pins at the start of the
instruction which helps configure the side pin of the
program.

<delay_value> : the number of clock cycles to delay after execution of
any instruction.

We also have directives which are listed as:

* .wrap_target : specifies where the program execution will get continued from

* .wrap : specifies the instruction where the control flow of the program will
get wrapped from.

* .word<value> : stores a raw 16-bit value which acts as an instruction to the
program.

* label : instruction offset of label used with jmp instruction.

We can take the pio_1hz example for a simple understanding. Below is the code
of pio_1hz.py for reference.

.. code-block:: python3

# Example using PIO to blink an LED and raise an IRQ at 1Hz.

import time
from machine import Pin
import rp2


@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def blink_1hz():
# fmt: off
# Cycles: 1 + 1 + 6 + 32 * (30 + 1) = 1000
irq(rel(0))
set(pins, 1)
set(x, 31) [5]
label("delay_high")
nop() [29]
jmp(x_dec, "delay_high")

# Cycles: 1 + 7 + 32 * (30 + 1) = 1000
set(pins, 0)
set(x, 31) [6]
label("delay_low")
nop() [29]
jmp(x_dec, "delay_low")
# fmt: on


# Create the StateMachine with the blink_1hz program, outputting on Pin(25).
sm = rp2.StateMachine(0, blink_1hz, freq=2000, set_base=Pin(25))

# Set the IRQ handler to print the millisecond timestamp.
sm.irq(lambda p: print(time.ticks_ms()))

# Start the StateMachine.
sm.active(1)

We are creating an object of class StateMachine which will display the output
on pin 25. The 'blink_1hz' program uses the PIO to blink an LED and raise the
IRQ at 1 HZ. Turn the LED on with the help of the set instruction. Set value
31 on register X. Then wait for 30 cycles with the help of nop() instruction.
Then with the help of jmp, go to the code part which has label as 'delay high'
for the instruction offset. The next part of the code teaches us to turn the
LED off by turning the LED off with the help of set instruction. Here the
label is 'delay_low' for the instruction offset part of the jmp instruction.

We then print the millisecond timestamp by setting the IRQ handler.



0