A template for my Rust projects with Raspberry Pi Pico.
Hi, this is my starting project template for my developments in Embedded Rust with the Raspberry Pi Pico (rp2040 micro-controller).
It is a example of a program developed with:
- The RTIC operating system or scheduler for ARM Micro-controllers.
- The USB-Serial emulation of a serial port, it can emulate other types of USB devices.
- Uf2 method of programming the Pico, but probe-run can also be used by uncommenting one line.
- It's an example of using shared and local state in RTIC.
- It's an example of using interrupts in RTIC.
- It's an example on processing the input from serial and sending a menu to serial terminal, printing long test, and format text with variables to serial terminal.
- It's an example of doing direct register access in Rust with PAC.
- It's an example of using the rp2040-hal.
- It's an example of using the rp-pico bsp abstraction layer.
I developed and tested this project in Linux Ubuntu 20.04, but it probably will compile and run in any computer (Linux, Windows, Mac and Raspberry Pi) connected to a Raspberry Pi Pico. This project feeds from several other projects.
This project was made after studying all Rust Pico examples and the RTIC book. By starting with the Project template for rp2040-hal configuring it to UF2 and changing it to suit my needs. I then added all the dependency libs for it to work with many of the examples of rp-pico board in the rp-hal and the examples in rp2040-hal in the rp-hal. Then I started with the code from example pico_rtic.rs and mixed it with the example pico_usb_serial.rs and pico_usb_serial_interrupt.rs but I couldn't make it all compile in RTIC. Then searched online for clues and arrived at Matrix chat room for the rp-hal https://matrix.to/#/#rp-rs:matrix.org. There I found a very warm and helpful community, that gave me links to examples of working USB in RTIC with Pico. Using this information I come up with this cool and useful (at least to me) project template. I extensively used the example that Paul Daniel Faria gave me - Nashenas88 - dactyl-manuform-kb2040-rs https://github.com/Nashenas88/dactyl-manuform-kb2040-rs.
- Low cost
- Dual core ARM Cortex M0 at 133 MHz that some people made it working at 420 MHZ
- 3.3V operating voltage
- 12MHz system crystal
- DMA controller
- JTAG/SWD header
- 2 MByte external Fash, 264 KByte SRAM
- 2x SPI, 2x USART, 2x I2C
- 16x PWM
- 30 GPIO Pins only at 3.3V (not 5V-tolerant)
- 1x USB 1.1 controller and PHY, with host and device support
- 1x ADC (12-bit / 5-channel / one temperature sensor)
- 30 GPIO pins, 4 of which can be used as analogue inputs
- 8x PIO - Programmable Input Output Controllers
- 3.3V LDO voltage regulator, max current 150mA
- Micro USB for power and data
- Onboard user LED (GPIO 25)
- 1x button for bootloader selection
- You can install a Reset button glued and soldered to the top of rp-pico board.
- 2x20 side pins + 1x3 SWD pins
- Note: Space to install a Reset button.
- See the datasheet for more accurate specs.
-
Install Rust on your computer.
Follow the Rust site steps.
https://www.rust-lang.org/ -
Install the packages specific to Embedded development and / or specific to Raspberry Pico.
Read the README.md page in
rp-hal - https://github.com/rp-rs/rp-hal
$ rustup self update
$ rustup update stable
$ rustup target add thumbv6m-none-eabi
# Useful to creating UF2 images for the RP2040 USB Bootloader
$ cargo install elf2uf2-rs --locked
# Useful for flashing over the SWD pins using a supported JTAG probe
$ cargo install probe-run
# Useful to detect stack overflow in your developed firmware.
$ cargo install flip-link
Configure your permissions to the USB-Serial port of your computer by your user.
# Connect the Pico and see the USB_Serial current connections
$ ls -l /dev/ttyUSB* /dev/ttyACM*
# Give permissions to the user to use the Serial port
$ usermod -a -G dialout $USER
-
Install a Serial Terminal program like
-
GTKTerminal
From the Ubuntu App install. -
or Install CuteCom
$ sudo apt install cutecom -
or this one, that is the one that I end up using more.
CoolTerm
Because it has a line mode, a better GUI and works in Linux, Windows and Mac.
https://freeware.the-meiers.org/
On the executable dochmod +x CoolTerm
-
-
Install a Serial Plot GUI
Very useful to easily monitor ADC plots.
SerialPlot - Realtime Plotting Software
https://hackaday.io/project/5334-serialplot-realtime-plotting-software
On the executable dochmod +x SerialPlot
-
Download the latest version of rp-hal github repo to a directory and unzip it.
rp-hal - Rust support for the "Raspberry Silicon" family of micro-controllers
https://github.com/rp-rs/rp-hal -
Download this project repository and unzip it to the some directory where you put the root of the previous rp-hal. Because we will be using it for the new version 4.0.0 of the rp2040-hal in our dependencies.
Raspberry Pi Pico in Rust Proj Template with RTIC USB-Serial and UF2 -
Change the project directory name from the unzip name to
rp2040-project-template-main
. -
Compile it and upload the firmware to the Raspberry Pico.
Remove the USB cable and press the white bootload button, while pressing, connect the cable again. It will enter in the USB - UF2 bootload mode that you can use to program the Pico by copyng the file (Cargo run does this automatically). Later you can install a Reset button in the Pico that will simplify this process.
# To Clean do:
$ cargo clean
$ clear
# To Compile and upload the firmware do:
$ cargo run --release
-
Open CoolTerm.
Then Menu -> Connection -> Options and select/dev/tttyACM0
115200 bps 8 N 1 (8 data bits, Parity None, Stop Bits 1). And in the Terminal choose "Line Mode" so that it will only send data when you press enter.
Then press "M" and the menu will appear. Then try the different options. -
Play with the code and understand it. See it, as an example of RTIC development with USB-Serial and UF2 programming and then change it (use it as a template) into your project. The only thing that you have to make is to change the root directory name into your project name and change the Cargo.toml file project name in the field
name = "rp2040-project-template"
. This file and your project name as to match, use only lower case letter and "-" or "_".
Note_1: UF2 - Make sure your .cargo/config.toml contains the following (it should by default if you are working in this repository for uf2 method):
[target.thumbv6m-none-eabi]
runner = "elf2uf2-rs -d"
Note_2: Compile and Run with probe-run and another Pico as a external debugger.
-
Loading with probe-run
See rp-hal page for more details.
Connect your USB JTAG/debug probe (such as a Raspberry Pi Pico running this firmware) to the SWD programming pins on your RP2040 board. -
Dapper Mime
https://github.com/majbthrd/DapperMime -
Connection diagram in here
https://user-images.githubusercontent.com/12226419/134785445-5f651d5a-eda9-4e94-8860-d2ef619dc27a.png
Note_3: For this project template you don't need the Rust nightly version but if you need you can change between stable and nightly versions by doing the following.
# To go to Rust nightly version
$ rustup default nightly
# The add the architecture support for the nightly
$ rustup target add thumbv6m-none-eabi
# To go back to Rust stable version do
$ rustup default stable
I tested the probe program firmware that should be loaded into a second Pico, the programmer. That allows you to program the first Pico. Rpi Pico-Probe from korken89 that implements a CMSIS DAP V1 and V2 Probe and it works well. Currently Pico-Probe is still under heavy development so many new features should appear but currently it already works well to program the Pico.
- korken89 – pico-probe
https://github.com/korken89/pico-probe
To program follow the instructions in the README.md
in the above link. You have to connect the two Pico’s. You have to compile the Pico-Probe, upload it as a UF2 and after that you can use it to program the target Pico.
# Don’t forget to change the .cargo/config.toml in my template project,
# comment the runner line for UF2 programming type
runner = "elf2uf2-rs -d"
# and uncomment the line
runner = "probe-run --chip RP2040"
# then do
$ cargo clean
$ cargo run --release
# to exit CMSIS DAP terminal do a ctrl + C
The connection diagram that I used (but you can change the pins in the Pico-Probe code setup.rs
) was:
Pin on programmer Pico | Description | Pin on target Pico |
---|---|---|
GPIO13 | nRESET | Run Pin |
GPIO14 | SWDIO | SWDIO in 3 pin header |
GPIO15 | SWCLK | SWCLK in 3 pin header |
VSYS | Power | VSYS |
GND | Ground | GND |
GND | Ground | GND in 3 pin header |
-
Book - Get Started with MicroPython on Raspberry Pi Pico
https://hackspace.raspberrypi.com/books/micropython-pico -
Video - An Overview of the Embedded Rust Ecosystem
https://www.youtube.com/watch?v=vLYit_HHPaY -
rp-hal - Rust support for the "Raspberry Silicon" family of micro-controllers
Your primary source of information for Rust developments with Raspberry Pico.
https://github.com/rp-rs/rp-hal -
Crate rp2040_hal - Docs
Your primary source of doc information on the HAL - Hardware Abstraction Layer.
https://docs.rs/rp2040-hal/latest/rp2040_hal/ -
Raspberry Pi Pico Board - Rust Code Examples
Study them all!
https://github.com/rp-rs/rp-hal/tree/main/boards/rp-pico/examples -
Examples for the HAL - Hardware Abstraction Layer
rp-hal - rp2040-hal - examples
https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal/examples -
Github rp2040-hal
https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal -
Getting Started with Rust on a Raspberry Pi Pico (Part 1)
https://reltech.substack.com/p/getting-started-with-rust-on-a-raspberry -
Getting Started with Rust on a Raspberry Pi Pico (Part 2)
https://reltech.substack.com/p/getting-started-with-raspberry-pi -
Getting Started with Rust on a Raspberry Pi Pico (Part 3)
https://reltech.substack.com/p/getting-started-with-rust-on-a-raspberry-a88 -
Multilingual blink for Raspberry Pi Pico - Alasdair Allan
https://www.raspberrypi.com/news/multilingual-blink-for-raspberry-pi-pico/ -
Video - How can we write the best device driver for a Hal in Rust?
https://www.youtube.com/watch?v=z9z74VpqO9A -
258 drivers para Embedded-HAL
https://crates.io/search?q=embedded-hal%20driver -
Video - RTIC - Real Time Interrupt driven Concurrency
RTIC is a RTOS - Real Time Operating System.
https://www.youtube.com/watch?v=saNdh0m_qHc -
RTIC Book
Real-Time Interrupt-driven Concurrency.
A very efficient preemptive multitasking framework that supports task prioritization and dead lock free execution.
https://rtic.rs/1/book/en/ -
Github - rtic-rs - cortex-m-rtic
https://github.com/rtic-rs/cortex-m-rtic -
Video - Grepit about the Rust RTIC framework
https://www.youtube.com/watch?v=sSJ-Md8nwIM -
Good example 1 of advanced Pico with RTIC to Study
Paul Daniel Faria
Nashenas88 - dactyl-manuform-kb2040-rs
Dactyl Manuform firmware for Adafruit kb2040 in Rust
https://github.com/Nashenas88/dactyl-manuform-kb2040-rs -
Good example 2 of advanced Pico with RTIC to Study
korken89
korken89 - pico-probe
https://github.com/korken89/pico-probe -
Good example 3 of advanced Pico with RTIC to Study
Mathias
mgottschlag - rp2040-usb-sound-card
https://github.com/mgottschlag/rp2040-usb-sound-card -
Good example 4 of advanced Pico with RTIC to Study
kalkyl - Playground for RTIC on RP2040
3 good examples
https://github.com/kalkyl/rp-rtic -
Project template for rp2040-hal
The starting point for the project that you are current reading.
https://github.com/rp-rs/rp2040-project-template -
pio-rs - Support for the Raspberry Silicon RP2040's PIO State Machines
https://github.com/rp-rs/pio-rs -
embedded-hal
Use this if you are writing code that should run on any micro-controller
https://github.com/rust-embedded/embedded-hal -
raspberrypi picotool - Not really neaded in Rust
https://github.com/raspberrypi/picotool -
usb-device - Experimental device-side USB stack for embedded devices
https://crates.io/crates/usb-device -
probe-rs - A modern, embedded debugging toolkit, written in Rust
https://probe.rs/ -
GitHub probe-rs
https://github.com/probe-rs/probe-rs -
Video - probe-rs: Your Embedded Tome
https://www.youtube.com/watch?v=esNPoXbhHkU -
rust-embedded - cortex-m-quickstart
https://github.com/rust-embedded/cortex-m-quickstart -
STM32 - Discovery - Book
https://docs.rust-embedded.org/discovery/ -
The Embedded Rust Book
https://docs.rust-embedded.org/book/ -
The Embedonomicon Book
Deep dive into the inner workings.
https://docs.rust-embedded.org/embedonomicon/ -
More gdb commands cheat-sheet
https://darkdust.net/files/GDB%20Cheat%20Sheet.pdf -
Video - Getting Started with Debugging using GDB
Find Bugs in Your Code with A Couple Easy Commands
https://www.youtube.com/watch?v=Dq8l1_-QgAc -
Play List - Embedded Rust BluePill - Vers Binarii
https://www.youtube.com/playlist?list=PLP_X41VhYn5X6Wwjnm0bRwI3n2pdaszxU -
Play List - Embedded Rust course - JaJakub - 2022
https://www.youtube.com/playlist?list=PLL2SCPK5xSRWBPj-nKOVYIhxRw7C4kYeI -
joaocarvalhoopen - stm32_bluepill_in_rust__Template
https://github.com/joaocarvalhoopen/stm32_bluepill_in_rust__Template -
Awesome Embedded Rust
https://github.com/rust-embedded/awesome-embedded-rust -
How to learn modern Rust
https://github.com/joaocarvalhoopen/How_to_learn_modern_Rust
-
Raspberry Pi Pico Site
https://www.raspberrypi.com/products/raspberry-pi-pico/ -
Pico RP2040 documentation
https://www.raspberrypi.com/documentation/microcontrollers/ -
RP2040 Micro-controller - Datasheet - PDF
https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf -
Pico board Datasheet - PDF
https://datasheets.raspberrypi.com/pico/pico-datasheet.pdf -
Pico C/C++ SDK - Libraries and Tools - PDF
https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf -
Pico Python SDK - PDF
https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-python-sdk.pdf -
Pico FAQ - PDF
https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-faq.pdf -
Raspberry Pi Pico Overclocking, beware there is a catch! - Part 1
The part 2 will resolve the flash issue.
https://www.youtube.com/watch?v=G2BuoFNLoDM -
Pico Overclock Part 2. Fixing the catch with the flash. - Part 2
https://www.youtube.com/watch?v=rU381A-b79c -
Play List - Raspberry Pi Pico - Low Level Learning
https://www.youtube.com/playlist?list=PLc7W4b0WHTAV6EYRVayb9c9dEsq-NeXAt -
Play List - Intro to Raspberry Pi Pico and RP2040 - DigiKey
https://www.youtube.com/playlist?list=PLEBQazB0HUyQO6rJxKr2umPCgmfAU-cqR -
Video - In-depth: Raspberry Pi Pico's PIO - programmable I/O
https://www.youtube.com/watch?v=yYnQYF_Xa8g -
Raspberry Pi Pico 200Khz Digital Oscilloscope
https://www.instructables.com/Raspberry-Pi-Pico-200Khz-Digital-Oscilloscope/ -
The Pico ADC
Integral Non-Linearity (INL) and Differential Non-Linearity (DNL) are used to measure the error of the quantization of the incoming signal that the ADC generates
Pag. 589 e Pag. 590 do Pico Datasheet
https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf -
Characterizing the Raspberry Pi Pico ADC - markomo
https://pico-adc.markomo.me/ -
Pico ADC - Power Supply Noise and Spectrum Testing
https://pico-adc.markomo.me/PSU-Noise/ -
Using a HD44780 LCD display with MicroPython on the Raspberry Pi Pico
https://raphaelkabo.com/blog/pi-pico-hd44780/ -
How to connect a piezo speaker to a microcontroller?
https://www.eevblog.com/forum/projects/how-to-connect-a-piezo-speaker-to-a-microcontroller/ -
Electrical Symbols & Electronic Symbols
https://www.rapidtables.com/electric/electrical_symbols.html
Solder a push button between the GND and Run pin's and then glue it over RP-Pico board empty space.
The Reset process to enter UF2 programming mode, instead of doing:
1. Remove USB Cable.
3. Press Bootload Button.
4. While pressing re-insert the USB cable.
5. Upload the C/C++ or Rust firmware
You will do:
1. Press the reset button.
2. Press the Bootload Button.
1. Release the reset button.
2. Release the Bootload Button.
5. Upload the C/C++ or Rust firmware
- Video - Pico Quick Reset Button
https://www.youtube.com/watch?v=OVM_spenILE
Order in which you should study the Rust examples for the RP2040 Micro-Controller and the RP-Pico Board
Use the following documentation while studying the examples:
-
Crate rp2040_hal - Docs
Your primary source of doc information on the HAL - Hardware Abstraction Layer.
https://docs.rs/rp2040-hal/latest/rp2040_hal/ -
RP2040 Micro-controller - Datasheet - PDF
https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf -
RTIC Book
Real-Time Interrupt-driven Concurrency.
A very efficient preemptive multitasking framework that supports task prioritization and dead lock free execution.
https://rtic.rs/1/book/en/
The examples:
- Examples for the RP-Pico Board
rp-hal - boards - rp-pico - examples
https://github.com/rp-rs/rp-hal/tree/main/boards/rp-pico/examples
1. - pico_blinky.rs
2. - pico_gpio_in_out.rs
3. - pico_rtic.rs
4. - pico_countdown_blinky.rs
5. - pico_pwm_blink.rs
6. - pico_usb_serial.rs
7. - pico_usb_serial_interrupt.rs
8. - pico_usb_twitchy_mouse.rs
9. - pico_uart_irq_buffer.rs
10. - pico_uart_irq_echo.rs
11. - pico_i2c_oled_display_ssd1306.rs
12. - pico_i2c_pio.rs
13. - pico_spi_sd_card.rs
14. - pico_ws2812_led.rs
- Examples for the HAL - Hardware Abstraction Layer
rp-hal - rp2040-hal - examples
https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal/examples
1. - blinky.rs
2. - gpio_in_out.rs
3. - multicore_fifo_blink.rs
4. - adc.rs
5. - lcd_display.rs
6. - watchdog.rs
7. - pwm_blink.rs
8. - rom_funcs.rs
9. - dht11.rs
11. - i2c.rs
12. - spi.rs
13. - uart.rs
14. - pio_blink.rs
15. - pio_proc_blink.rs
16. - pio_side_set.rs
Then study My example Template.
Then the following RTIC examples with USB.
-
Good example 1 of advanced Pico with RTIC to Study
Paul Daniel Faria
Nashenas88 - dactyl-manuform-kb2040-rs
Dactyl Manuform firmware for Adafruit kb2040 in Rust
https://github.com/Nashenas88/dactyl-manuform-kb2040-rs -
Good example 2 of advanced Pico with RTIC to Study
korken89
korken89 - pico-probe
https://github.com/korken89/pico-probe -
Good example 3 of advanced Pico with RTIC to Study
Mathias
mgottschlag - rp2040-usb-sound-card
https://github.com/mgottschlag/rp2040-usb-sound-card -
Good example 4 of advanced Pico with RTIC to Study
kalkyl - Playground for RTIC on RP2040
3 good examples
https://github.com/kalkyl/rp-rtic
First if possible try to use RTIC framework for concurrency. It’s like a small and lightweight operating system that simplifies the development process.
Then you should use BSP (Board level support package) features where available.
Then use rp2040-hal (Hardware Abstraction Layer) features for the majority of development and if you need something that is not yet supported by the HAL or if you need a more fine grained control over the hardware, you should use rp2040-pac (Peripheral Access Crate) direct access through the registers and consult the rp2040 datasheet to discover each register name, what each register do and how to use them.
-
Crate rp2040_pac
https://docs.rs/rp2040-pac/0.3.0/rp2040_pac/ -
To know how the syntax to access and use the registers see...
svd2rust
https://docs.rs/svd2rust/0.21.0/svd2rust/#peripheral-api -
RP2040 Micro-controller - Datasheet - PDF
https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf
// Example
use rp_pico::hal;
use rp_pico::pac;
let led_status_reg = unsafe { (*pac::IO_BANK0::ptr()).gpio[25].gpio_status.read().bits() };
let sio_pin_value = unsafe { (*pac::SIO::ptr()).gpio_out.read().bits() };
let (led_bool, led_str) = if ((led_status_reg & 1 << 8) >> 8) == 1_u32 {
(true, "ON")
} else {
(false, "OFF")
};
The contents of this repository are dual-licensed under the MIT OR Apache
2.0 License. That means you can chose either the MIT licence or the
Apache-2.0 licence when you re-use this code. See MIT
or APACHE2.0
for more
information on each specific licence.
Best regards,
João Nuno Carvalho