8000 rp2: Add new port to Raspberry Pi RP2 microcontroller. · micropython/micropython@469345e · GitHub
[go: up one dir, main page]

Skip to content

Commit 469345e

Browse files
committed
rp2: Add new port to Raspberry Pi RP2 microcontroller.
This commit adds a new port "rp2" which targets the new Raspberry Pi RP2040 microcontroller. The build system uses pure cmake (with a small Makefile wrapper for convenience). The USB driver is TinyUSB, and there is a machine module with most of the standard classes implemented. Some examples are provided in the examples/rp2/ directory. Work done in collaboration with Graham Sanderson. Signed-off-by: Damien George <damien@micropython.org>
1 parent ef3ee7a commit 469345e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+5509
-0
lines changed

examples/rp2/pio_1hz.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Example using PIO to blink an LED and raise an IRQ at 1Hz.
2+
3+
import time
4+
from machine import Pin
5+
import rp2
6+
7+
8+
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
9+
def blink_1hz():
10+
# fmt: off
11+
# Cycles: 1 + 1 + 6 + 32 * (30 + 1) = 1000
12+
irq(rel(0))
13+
set(pins, 1)
14+
set(x, 31) [5]
15+
label("delay_high")
16+
nop() [29]
17+
jmp(x_dec, "delay_high")
18+
19+
# Cycles: 1 + 7 + 32 * (30 + 1) = 1000
20+
set(pins, 0)
21+
set(x, 31) [6]
22+
label("delay_low")
23+
nop() [29]
24+
jmp(x_dec, "delay_low")
25+
# fmt: on
26+
27+
28+
# Create the StateMachine with the blink_1hz program, outputting on Pin(25).
29+
sm = rp2.StateMachine(0, blink_1hz, freq=2000, set_base=Pin(25))
30+
31+
# Set the IRQ handler to print the millisecond timestamp.
32+
sm.irq(lambda p: print(time.ticks_ms()))
33+
34+
# Start the StateMachine.
35+
sm.active(1)

examples/rp2/pio_exec.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Example using PIO to turn on an LED via an explicit exec.
2+
#
3+
# Demonstrates:
4+
# - using set_init and set_base
5+
# - using StateMachine.exec
6+
7+
import time
8+
from machine import Pin
9+
import rp2
10+
11+
# Define an empty program that uses a single set pin.
12+
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
13+
def prog():
14+
pass
15+
16+
17+
# Construct the StateMachine, binding Pin(25) to the set pin.
18+
sm = rp2.StateMachine(0, prog, set_base=Pin(25))
19+
20+
# Turn on the set pin via an exec instruction.
21+
sm.exec("set(pins, 1)")
22+
23+
# Sleep for 500ms.
24+
time.sleep(0.5)
25+
26+
# Turn off the set pin via an exec instruction.
27+
sm.exec("set(pins, 0)")

examples/rp2/pio_pinchange.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Example using PIO to wait for a pin change and raise an IRQ.
2+
#
3+
# Demonstrates:
4+
# - PIO wrapping
5+
# - PIO wait instruction, waiting on an input pin
6+
# - PIO irq instruction, in blocking mode with relative IRQ number
7+
# - setting the in_base pin for a StateMachine
8+
# - setting an irq handler for a StateMachine
9+
# - instantiating 2x StateMachine's with the same program and different pins
10+
11+
import time
12+
from machine import Pin
13+
import rp2
14+
15+
16+
@rp2.asm_pio()
17+
def wait_pin_low():
18+
wrap_target()
19+
20+
wait(0, pin, 0)
21+
irq(block, rel(0))
22+
wait(1, pin, 0)
23+
24+
wrap()
25+
26+
27+
def handler(sm):
28+
# Print a (wrapping) timestamp, and the state machine object.
29+
print(time.ticks_ms(), sm)
30+
31+
32+
# Instantiate StateMachine(0) with wait_pin_low program on Pin(16).
33+
pin16 = Pin(16, Pin.IN, Pin.PULL_UP)
34+
sm0 = rp2.StateMachine(0, wait_pin_low, in_base=pin16)
35+
sm0.irq(handler)
36+
37+
# Instantiate StateMachine(1) with wait_pin_low program on Pin(17).
38+
pin17 = Pin(17, Pin.IN, Pin.PULL_UP)
39+
sm1 = rp2.StateMachine(1, wait_pin_low, in_base=pin17)
40+
sm1.irq(handler)
41+
42+
# Start the StateMachine's running.
43+
sm0.active(1)
44+
sm1.active(1)
45+
46+
# Now, when Pin(16) or Pin(17) is pulled low a message will be printed to the REPL.

examples/rp2/pio_pwm.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Example of using PIO for PWM, and fading the brightness of an LED
2+
3+
from machine import Pin
4+
from rp2 import PIO, StateMachine, asm_pio
5+
from time import sleep
6+
7+
8+
@asm_pio(sideset_init=PIO.OUT_LOW)
9+
def pwm_prog():
10+
# fmt: off
11+
pull(noblock) .side(0)
12+
mov(x, osr) # Keep most recent pull data stashed in X, for recycling by noblock
13+
mov(y, isr) # ISR must be preloaded with PWM count max
14+
label("pwmloop")
15+
jmp(x_not_y, "skip")
16+
nop() .side(1)
17+
label("skip")
18+
jmp(y_dec, "pwmloop")
19+
# fmt: on
20+
21+
22+
class PIOPWM:
23+
def __init__(self, sm_id, pin, max_count, count_freq):
24+
self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin))
25+
# Use exec() to load max count into ISR
26+
self._sm.put(max_count)
27+
self._sm.exec("pull()")
28+
self._sm.exec("mov(isr, osr)")
29+
self._sm.active(1)
30+
self._max_count = max_count
31+
32+
def set(self, value):
33+
# Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse
34+
value = max(value, -1)
35+
value = min(value, self._max_count)
36+
self._sm.put(value)
37+
38+
39+
# Pin 25 is LED on Pico boards
40+
pwm = PIOPWM(0, 25, max_count=(1 << 16) - 1, count_freq=10_000_000)
41+
42+
while True:
43+
for i in range(256):
44+
pwm.set(i ** 2)
45+
sleep(0.01)

examples/rp2/pio_uart_tx.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Example using PIO to create a UART TX interface
2+
3+
from machine import Pin
4+
from rp2 import PIO, StateMachine, asm_pio
5+
6+
UART_BAUD = 115200
7+
PIN_BASE = 10
8+
NUM_UARTS = 8
9+
10+
11+
@asm_pio(sideset_init=PIO.OUT_HIGH, out_init=PIO.OUT_HIGH, out_shiftdir=PIO.SHIFT_RIGHT)
12+
def uart_tx():
13+
# fmt: off
14+
# Block with TX deasserted until data available
15+
pull()
16+
# Initialise bit counter, assert start bit for 8 cycles
17+
set(x, 7) .side(0) [7]
18+
# Shift out 8 data bits, 8 execution cycles per bit
19+
label("bitloop")
20+
out(pins, 1) [6]
21+
jmp(x_dec, "bitloop")
22+
# Assert stop bit for 8 cycles total (incl 1 for pull())
23+
nop() .side(1) [6]
24+
# fmt: on
25+
26+
27+
# Now we add 8 UART TXs, on pins 10 to 17. Use the same baud rate for all of them.
28+
uarts = []
29+
for i in range(NUM_UARTS):
30+
sm = StateMachine(
31+
i, uart_tx, freq=8 * UART_BAUD, sideset_base=Pin(PIN_BASE + i), out_base=Pin(PIN_BASE + i)
32+
)
33+
sm.active(1)
34+
uarts.append(sm)
35+
36+
# We can print characters from each UART by pushing them to the TX FIFO
37+
def pio_uart_print(sm, s):
38+
for c in s:
39+
sm.put(ord(c))
40+
41+
42+
# Print a different message from each UART
43+
for i, u in enumerate(uarts):
44+
pio_uart_print(u, "Hello from UART {}!\n".format(i))

examples/rp2/pio_ws2812.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Example using PIO to drive a set of WS2812 LEDs.
2+
3+
import array, time
4+
from machine import Pin
5+
import rp2
6+
7+
# Configure the number of WS2812 LEDs.
8+
NUM_LEDS = 8
9+
10+
11+
@rp2.asm_pio(
12+
sideset_init=rp2.PIO.OUT_LOW,
13+
out_shiftdir=rp2.PIO.SHIFT_LEFT,
14+
autopull=True,
15+
pull_thresh=24,
16+
)
17+
def ws2812():
18+
# fmt: off
19+
T1 = 2
20+
T2 = 5
21+
T3 = 3
22+
wrap_target()
23+
label("bitloop")
24+
out(x, 1) .side(0) [T3 - 1]
25+
jmp(not_x, "do_zero") .side(1) [T1 - 1]
26+
jmp("bitloop") .side(1) [T2 - 1]
27+
label("do_zero")
28+
nop() .side(0) [T2 - 1]
29+
wrap()
30+
# fmt: on
31+
32+
33+
# Create the StateMachine with the ws2812 program, outputting on Pin(22).
34+
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(22))
35+
36+
# Start the StateMachine, it will wait for data on its FIFO.
37+
sm.active(1)
38+
39+
# Display a pattern on the LEDs via an array of LED RGB values.
40+
ar = array.array("I", [0 for _ in range(NUM_LEDS)])
41+
42+
# Cycle colours.
43+
for i in range(4 * NUM_LEDS):
44+
for j in range(NUM_LEDS):
45+
r = j * 100 // (NUM_LEDS - 1)
46+
b = 100 - j * 100 // (NUM_LEDS - 1)
47+
if j != i % NUM_LEDS:
48+
r >>= 3
49+
b >>= 3
50+
ar[j] = r << 16 | b
51+
sm.put(ar, 8)
52+
time.sleep_ms(50)
53+
54+
# Fade out.
55+
for i in range(24):
56+
for j in range(NUM_LEDS):
57+
ar[j] = ar[j] >> 1 & 0x7F7F7F
58+
sm.put(ar, 8)
59+
time.sleep_ms(50)

examples/rp2/pwm_fade.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Example using PWM to fade an LED.
2+
3+
import time
4+
from machine import Pin, PWM
5+
6+
7+
# Construct PWM object, with LED on Pin(25).
8+
pwm = PWM(Pin(25))
9+
10+
# Set the PWM frequency.
11+
pwm.freq(1000)
12+
13+
# Fade the LED in and out a few times.
14+
duty = 0
15+
direction = 1
16+
for _ in range(8 * 256):
17+
duty += direction
18+
if duty > 255:
19+
duty = 255
20+
direction = -1
21+
elif duty < 0:
22+
duty = 0
23+
direction = 1
24+
pwm.duty_u16(duty * duty)
25+
time.sleep(0.001)

0 commit comments

Comments
 (0)
0