diff --git a/.cargo/config b/.cargo/config
index 55974e3..6486a00 100644
--- a/.cargo/config
+++ b/.cargo/config
@@ -10,3 +10,4 @@ rustflags = [
"-C", "no-vectorize-loops",
]
runner = "elf2uf2-rs -d"
+# runner = "probe-run-rp --chip RP2040"
diff --git a/README.md b/README.md
index 808656a..5c30850 100644
--- a/README.md
+++ b/README.md
@@ -8,26 +8,26 @@
rp-hal
- A Rust HAL and board support packages for the RP family of microcontrollers from the Raspberry Pi Foundation
+ Rust support for the "Raspberry Silicon" family of microcontrollers
- Explore the docs »
+ Explore the API docs »
- View Demo
+ View Demos
·
- Report Bug
+ Report a Bug
·
- Request Feature
+ Chat on Matrix
-
Table of Contents
- - Packages
+ - Getting Started
+ - Programming
- Roadmap
- Contributing
- License
@@ -37,6 +37,45 @@
+
+## Getting Started
+
+So, you want to program your new Raspberry Silicon microcontroller, using the
+Rust programming language. You've come to the right place!
+
+This repository is `rp-hal` - a collection of high-level drivers for the
+Raspberry Silicon RP2040 microcontroller and various associated boards, like
+the Raspberry Pi Pico and the Adafruit Feather RP2040.
+
+If you want to write an application for Raspberry Silicon, check out our
+[RP2040 Project Template](https://github.com/rp-rs/rp2040-project-template).
+
+If you want to write code that uses the Raspberry Silicon PIO State Machines,
+check out [pio-rs](https://github.com/rp-rs/pio-rs). You can even compile PIO
+programs at run-time, on the RP2040 itself!
+
+If you want to try out some examples on one of our supported boards, check out
+the list of *Board Support Packages* below, and click through to see the various
+examples for each board.
+
+Before trying any of the examples, please ensure you have the latest stable
+version of Rust installed, along with the right target support:
+
+```sh
+rustup self update
+rustup update stable
+rustup target add thumbv6m-none-eabi
+```
+
+You may also want to install these helpful tools:
+
+```sh
+# Useful to creating UF2 images for the RP2040 USB Bootloader
+cargo install elf2uf2-rs
+# Useful for flashing over the SWD pins using a supported JTAG probe
+cargo install --git https://github.com/rp-rs/probe-run.git --branch rp2040-support
+```
+
## Packages
This git repository is organised as a [Cargo Workspace].
@@ -52,16 +91,16 @@ crate (which will include the _HAL_ crate for you). Please note, you cannot
depend on multiple _BSP_ crates; you have to pick one, or use [Cargo Features]
to select one at build time.
-Each BSP will include some examples to show off the features of that particular board.
+Each BSP includes some examples to show off the features of that particular board.
[Cargo Workspace]: https://doc.rust-lang.org/cargo/reference/workspaces.html]
[Embedded HAL]: https://github.com/rust-embedded/embedded-hal
[Cargo Features]: https://doc.rust-lang.org/cargo/reference/features.html
-### [rp2040-hal] - The HAL for the [Raspberry Pi Silicon RP2040]
+### [rp2040-hal] - The HAL for the [Raspberry Silicon RP2040]
You should include this crate in your project if you want to write a driver or
-library that runs on the [Raspberry Pi Silicon RP2040], or if you are writing a Board
+library that runs on the [Raspberry Silicon RP2040], or if you are writing a Board
Support Package (see later on).
The crate provides high-level drivers for the RP2040's internal peripherals,
@@ -74,7 +113,7 @@ There are examples in this crate to show how to use various peripherals
particular board.
[rp2040-hal]: https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal
-[Raspberry Pi Silicon RP2040]: https://www.raspberrypi.org/products/rp2040/
+[Raspberry Silicon RP2040]: https://www.raspberrypi.org/products/rp2040/
### [pico] - Board Support for the [Raspberry Pi Pico]
@@ -147,12 +186,130 @@ RP2040 chip according to how it is connected up on the Pro Micro RP2040.
[Sparkfun Pro Micro RP2040]: https://www.sparkfun.com/products/18288
[pro_micro_rp2040]: https://github.com/rp-rs/rp-hal/tree/main/boards/pro_micro_rp2040
+
+## Programming
+
+Rust generates standard Arm ELF files, which you can load onto your Raspberry Pi
+Silicon device with your favourite Arm flashing/debugging tool. In addition, the
+RP2040 contains a ROM bootloader which appears as a Mass Storage Device over USB
+that accepts UF2 format images. You can use the `elf2uf2-rs` package to convert
+the Arm ELF file to a UF2 format image.
+
+For boards with USB Device support like the Raspberry Pi Pico, we recommend you
+use the UF2 process.
+
+The RP2040 contains two Cortex-M0+ processors, which execute Thumb-2 encoded
+ARMv6-M instructions. There are no operating-specific features in the binaries
+produced - they are for 'bare-metal' systems. For compatibilty with other Arm
+code (e.g. as produced by GCC), Rust uses the *Arm Embedded-Application Binary
+Interface* standard or EABI. Therefore, any Rust code for the RP2040 should be
+compiled with the target *`thumbv6m-none-eabi`*.
+
+More details can be found in the [Project Template](https://github.com/rp-rs/rp2040-project-template).
+
+### Loading a UF2 over USB
+
+*Step 1* - Install [`elf2uf2-rs`](https://github.com/JoNil/elf2uf2-rs):
+
+```console
+$ cargo install elf2uf2-rs
+```
+
+*Step 2* - Make sure your .cargo/config contains the following (it should by
+default if you are working in this repository):
+
+```toml
+[target.thumbv6m-none-eabi]
+runner = "elf2uf2-rs -d"
+```
+
+The `thumbv6m-none-eabi` target may be replaced by the all-Arm wildcard
+`'cfg(all(target_arch = "arm", target_os = "none"))'`.
+
+*Step 3* - Boot your RP2040 into "USB Bootloader mode", typically by rebooting
+whilst holding some kind of "Boot Select" button. On Linux, you will also need
+to 'mount' the device, like you would a USB Thumb Drive.
+
+*Step 4* - Use `cargo run`, which will compile the code and started the
+specified 'runner'. As the 'runner' is the elf2uf2-rs tool, it will build a UF2
+file and copy it to your RP2040.
+
+```console
+$ cargo run --release --example pico_pwm_blink
+```
+
+### Loading with probe-run
+
+The Knurling project has a tool called
+[probe-run](https://github.com/knurling-rs/probe-run). This is a command-line
+tool which can flash a wide variety of microcontrollers using a wide variety of
+debug/JTAG probes. It is based on a library called
+[probe-rs](https://github.com/probe-rs/probe-rs). Unlike using, say, OpenOCD,
+probe-rs can autodetect your debug probe, which can make it easier to use.
+
+Currently, probe-rs supports the slightly unusual debug hardware in the RP2040,
+but the last released probe-run tool (v0.2.6, as of September 2021), does not.
+However, there is a special version of probe-run for the RP2040 called
+[probe-run-rp](https://github.com/rp-rs/probe-run/tree/rp2040-support).
+
+*Step 1* - Install `probe-run-rp`:
+
+```console
+$ cargo install --git https://github.com/rp-rs/probe-run.git --branch rp2040-support
+```
+
+*Step 2* - Make sure your .cargo/config contains the following:
+
+```toml
+[target.thumbv6m-none-eabi]
+runner = "probe-run-rp --chip RP2040"
+```
+
+*Step 3* - Connect your USB JTAG/debug probe (such as a Raspberry Pi Pico
+running [this firmware](https://github.com/majbthrd/DapperMime)) to the SWD
+programming pins on your RP2040 board. Check the probe has been found by
+running:
+
+```console
+$ probe-run-rp --chip RP2040 --list-probes
+The following devices were found:
+[0]: J-Link (J-Link) (VID: 1366, PID: 0101, Serial: 000099999999, JLink)
+```
+
+There is a SEGGER J-Link connected in the example above - the mesage you see
+will reflect the probe you have connected.
+
+*Step 4* - Use `cargo run`, which will compile the code and start the specified
+'runner'. As the 'runner' is the `probe-run-rp` tool, it will connect to the
+RP2040 via the first probe it finds, and install your firmware into the Flash
+connected to the RP2040.
+
+```console
+$ cargo run --release --example pico_pwm_blink
+```
+
+### Loading with picotool
+
+As ELF files produced by compiling Rust code are completely compatible with ELF
+files produced by compiling C or C++ code, you can also use the Raspberry Pi
+tool [picoprobe](https://github.com/raspberrypi/picotool). The only thing to be
+aware of is that picotool expects your ELF files to have a `.elf` extension, and
+by default Rust does not give the ELF files any extension. You can fix this by
+simply renaming the file.
+
+Also of note is that the special
+[pico-sdk](https://github.com/raspberrypi/pico-sdk) macros which hide
+information in the ELF file in a way that `picotool info` can read it out, are
+not supported in Rust. An alternative is TBC.
+
## Roadmap
-NOTE These packages are under active development. As such, it is likely to remain volatile until a 1.0.0 release.
+NOTE These packages are under active development. As such, it is likely to
+remain volatile until a 1.0.0 release.
-See the [open issues](https://github.com/rp-rs/rp-hal/issues) for a list of proposed features (and known issues).
+See the [open issues](https://github.com/rp-rs/rp-hal/issues) for a list of
+proposed features (and known issues).
@@ -195,9 +352,8 @@ under these terms.
## Contact
-Project Link: [https://github.com/rp-rs/rp-hal/issues](https://github.com/rp-rs/rp-hal/issues)
-Matrix: [#rp-rs:matrix.org](https://matrix.to/#/#rp-rs:matrix.org)
-
+Raise an issue: [https://github.com/rp-rs/rp-hal/issues](https://github.com/rp-rs/rp-hal/issues)
+Chat to us on Matrix: [#rp-rs:matrix.org](https://matrix.to/#/#rp-rs:matrix.org)
## Acknowledgements
diff --git a/boards/adafruit_macropad/README.md b/boards/adafruit_macropad/README.md
index dc2bdd9..b5875dd 100644
--- a/boards/adafruit_macropad/README.md
+++ b/boards/adafruit_macropad/README.md
@@ -9,7 +9,7 @@ RP2040 chip according to how it is connected up on the Feather.
[adafruit_macropad]: https://github.com/rp-rs/rp-hal/tree/main/boards/adafruit_macropad
[Adafruit Macropad]: https://www.adafruit.com/product/5128
[rp2040-hal]: https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal
-[Raspberry Pi Silicon RP2040]: https://www.raspberrypi.org/products/rp2040/
+[Raspberry Silicon RP2040]: https://www.raspberrypi.org/products/rp2040/
## Using
diff --git a/boards/feather_rp2040/README.md b/boards/feather_rp2040/README.md
index 42833e1..76f9173 100644
--- a/boards/feather_rp2040/README.md
+++ b/boards/feather_rp2040/README.md
@@ -9,7 +9,7 @@ RP2040 chip according to how it is connected up on the Feather.
[Adafruit Feather RP2040]: https://www.adafruit.com/product/4884
[feather_rp2040]: https://github.com/rp-rs/rp-hal/tree/main/boards/feather_rp2040
[rp2040-hal]: https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal
-[Raspberry Pi Silicon RP2040]: https://www.raspberrypi.org/products/rp2040/
+[Raspberry Silicon RP2040]: https://www.raspberrypi.org/products/rp2040/
## Using
diff --git a/boards/pico/README.md b/boards/pico/README.md
index 2ab637d..5470fb4 100644
--- a/boards/pico/README.md
+++ b/boards/pico/README.md
@@ -9,7 +9,7 @@ RP2040 chip according to how it is connected up on the Pico.
[Raspberry Pi Pico]: https://www.raspberrypi.org/products/raspberry-pi-pico/
[pico]: https://github.com/rp-rs/rp-hal/tree/main/boards/pico
[rp2040-hal]: https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal
-[Raspberry Pi Silicon RP2040]: https://www.raspberrypi.org/products/rp2040/
+[Raspberry Silicon RP2040]: https://www.raspberrypi.org/products/rp2040/
## Using
diff --git a/boards/pico/examples/pico_blinky.rs b/boards/pico/examples/pico_blinky.rs
index 7bb82ee..2970ee5 100644
--- a/boards/pico/examples/pico_blinky.rs
+++ b/boards/pico/examples/pico_blinky.rs
@@ -34,8 +34,8 @@ use pico::hal::pac;
// higher-level drivers.
use pico::hal;
-/// The linker will place this boot block at the start of our program image. We
-/// need this to help the ROM bootloader get our code up and running.
+//// The linker will place this boot block at the start of our program image. We
+//// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
@@ -58,7 +58,7 @@ fn main() -> ! {
// Configure the clocks
//
- // Our default is 12 MHz crystal input, 125 MHz system clock
+ // The default is to generate a 125 MHz system clock
let clocks = hal::clocks::init_clocks_and_plls(
pico::XOSC_CRYSTAL_FREQ,
pac.XOSC,
diff --git a/boards/pico/examples/pico_countdown_blinky.rs b/boards/pico/examples/pico_countdown_blinky.rs
index cb4a13d..f6a3ea7 100644
--- a/boards/pico/examples/pico_countdown_blinky.rs
+++ b/boards/pico/examples/pico_countdown_blinky.rs
@@ -47,7 +47,7 @@ fn main() -> ! {
// Configure the clocks
//
- // Our default is 12 MHz crystal input, 125 MHz system clock
+ // The default is to generate a 125 MHz system clock
let _clocks = hal::clocks::init_clocks_and_plls(
pico::XOSC_CRYSTAL_FREQ,
pac.XOSC,
diff --git a/boards/pico/examples/pico_gpio_in_out.rs b/boards/pico/examples/pico_gpio_in_out.rs
index d2c446e..81d1c9b 100644
--- a/boards/pico/examples/pico_gpio_in_out.rs
+++ b/boards/pico/examples/pico_gpio_in_out.rs
@@ -30,8 +30,8 @@ use pico::hal::pac;
// higher-level drivers.
use pico::hal;
-/// The linker will place this boot block at the start of our program image. We
-/// need this to help the ROM bootloader get our code up and running.
+//// The linker will place this boot block at the start of our program image. We
+//// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
diff --git a/boards/pico/examples/pico_pwm_blink.rs b/boards/pico/examples/pico_pwm_blink.rs
index 9bd1eb5..16b48f8 100644
--- a/boards/pico/examples/pico_pwm_blink.rs
+++ b/boards/pico/examples/pico_pwm_blink.rs
@@ -34,8 +34,8 @@ use pico::hal::pac;
// higher-level drivers.
use pico::hal;
-/// The linker will place this boot block at the start of our program image. We
-/// need this to help the ROM bootloader get our code up and running.
+//// The linker will place this boot block at the start of our program image. We
+//// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
@@ -64,7 +64,7 @@ fn main() -> ! {
// Configure the clocks
//
- // Our default is 12 MHz crystal input, 125 MHz system clock
+ // The default is to generate a 125 MHz system clock
let clocks = hal::clocks::init_clocks_and_plls(
pico::XOSC_CRYSTAL_FREQ,
pac.XOSC,
diff --git a/boards/pico/examples/pico_usb_serial.rs b/boards/pico/examples/pico_usb_serial.rs
index 8a69aed..2732da2 100644
--- a/boards/pico/examples/pico_usb_serial.rs
+++ b/boards/pico/examples/pico_usb_serial.rs
@@ -33,8 +33,8 @@ use usb_device::{class_prelude::*, prelude::*};
// USB Communications Class Device support
use usbd_serial::SerialPort;
-/// The linker will place this boot block at the start of our program image. We
-/// need this to help the ROM bootloader get our code up and running.
+//// The linker will place this boot block at the start of our program image. We
+//// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
@@ -56,7 +56,7 @@ fn main() -> ! {
// Configure the clocks
//
- // Our default is 12 MHz crystal input, 125 MHz system clock
+ // The default is to generate a 125 MHz system clock
let clocks = hal::clocks::init_clocks_and_plls(
pico::XOSC_CRYSTAL_FREQ,
pac.XOSC,
diff --git a/boards/pico/examples/pico_usb_serial_interrupt.rs b/boards/pico/examples/pico_usb_serial_interrupt.rs
index 6d9fd5c..e5b8fe6 100644
--- a/boards/pico/examples/pico_usb_serial_interrupt.rs
+++ b/boards/pico/examples/pico_usb_serial_interrupt.rs
@@ -45,8 +45,8 @@ use usb_device::{class_prelude::*, prelude::*};
// USB Communications Class Device support
use usbd_serial::SerialPort;
-/// The linker will place this boot block at the start of our program image. We
-/// need this to help the ROM bootloader get our code up and running.
+//// The linker will place this boot block at the start of our program image. We
+//// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
@@ -78,7 +78,7 @@ fn main() -> ! {
// Configure the clocks
//
- // Our default is 12 MHz crystal input, 125 MHz system clock
+ // The default is to generate a 125 MHz system clock
let clocks = hal::clocks::init_clocks_and_plls(
pico::XOSC_CRYSTAL_FREQ,
pac.XOSC,
diff --git a/boards/pico/examples/pico_usb_twitchy_mouse.rs b/boards/pico/examples/pico_usb_twitchy_mouse.rs
index 0215bf3..76fff72 100644
--- a/boards/pico/examples/pico_usb_twitchy_mouse.rs
+++ b/boards/pico/examples/pico_usb_twitchy_mouse.rs
@@ -44,8 +44,8 @@ use usbd_hid::descriptor::generator_prelude::*;
use usbd_hid::descriptor::MouseReport;
use usbd_hid::hid_class::HIDClass;
-/// The linker will place this boot block at the start of our program image. We
-/// need this to help the ROM bootloader get our code up and running.
+//// The linker will place this boot block at the start of our program image. We
+//// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
@@ -76,7 +76,7 @@ fn main() -> ! {
// Configure the clocks
//
- // Our default is 12 MHz crystal input, 125 MHz system clock
+ // The default is to generate a 125 MHz system clock
let clocks = hal::clocks::init_clocks_and_plls(
pico::XOSC_CRYSTAL_FREQ,
pac.XOSC,
diff --git a/boards/pico_explorer/README.md b/boards/pico_explorer/README.md
index c9167d2..25e99e1 100644
--- a/boards/pico_explorer/README.md
+++ b/boards/pico_explorer/README.md
@@ -10,7 +10,7 @@ RP2040 chip according to how it is connected up on the Pico Explorer.
[Pimoroni Pico Explorer]: https://shop.pimoroni.com/products/pico-explorer-base
[pico_explorer]: https://github.com/rp-rs/rp-hal/tree/main/boards/pico_explorer
[rp2040-hal]: https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal
-[Raspberry Pi Silicon RP2040]: https://www.raspberrypi.org/products/rp2040/
+[Raspberry Silicon RP2040]: https://www.raspberrypi.org/products/rp2040/
## Using
diff --git a/boards/pico_lipo_16mb/examples/pico_lipo_16mb_blinky.rs b/boards/pico_lipo_16mb/examples/pico_lipo_16mb_blinky.rs
index 0fc65f5..b5e4318 100644
--- a/boards/pico_lipo_16mb/examples/pico_lipo_16mb_blinky.rs
+++ b/boards/pico_lipo_16mb/examples/pico_lipo_16mb_blinky.rs
@@ -34,8 +34,8 @@ use pico_lipo_16_mb::hal::pac;
// higher-level drivers.
use pico_lipo_16_mb::hal;
-/// The linker will place this boot block at the start of our program image. We
-/// need this to help the ROM bootloader get our code up and running.
+//// The linker will place this boot block at the start of our program image. We
+//// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
@@ -58,7 +58,7 @@ fn main() -> ! {
// Configure the clocks
//
- // Our default is 12 MHz crystal input, 125 MHz system clock
+ // The default is to generate a 125 MHz system clock
let clocks = hal::clocks::init_clocks_and_plls(
pico_lipo_16_mb::XOSC_CRYSTAL_FREQ,
pac.XOSC,
diff --git a/boards/pro_micro_rp2040/README.md b/boards/pro_micro_rp2040/README.md
index 40ad916..60abd8c 100644
--- a/boards/pro_micro_rp2040/README.md
+++ b/boards/pro_micro_rp2040/README.md
@@ -1,7 +1,7 @@
# [pro_micro_rp2040] - Board Support for the [Sparkfun Pro Micro RP2040]
You should include this crate if you are writing code that you want to run on
-a [Sparkfun Pro Micro RP2040] - a smaller [RP2040][Raspberry Pi Silicon RP2040] board with USB-C and a WS2812B addressable LED.
+a [Sparkfun Pro Micro RP2040] - a smaller [RP2040][Raspberry Silicon RP2040] board with USB-C and a WS2812B addressable LED.
This crate includes the [rp2040-hal], but also configures each pin of the
RP2040 chip according to how it is connected up on the Pro Micro RP2040.
@@ -9,7 +9,7 @@ RP2040 chip according to how it is connected up on the Pro Micro RP2040.
[Sparkfun Pro Micro RP2040]: https://www.sparkfun.com/products/18288
[pro_micro_rp2040]: https://github.com/rp-rs/rp-hal/tree/main/boards/pro_micro_rp2040
[rp2040-hal]: https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal
-[Raspberry Pi Silicon RP2040]: https://www.raspberrypi.org/products/rp2040/
+[Raspberry Silicon RP2040]: https://www.raspberrypi.org/products/rp2040/
## Using
diff --git a/boards/pro_micro_rp2040/examples/pro_micro_rainbow.rs b/boards/pro_micro_rp2040/examples/pro_micro_rainbow.rs
index f84a296..dd9a094 100644
--- a/boards/pro_micro_rp2040/examples/pro_micro_rainbow.rs
+++ b/boards/pro_micro_rp2040/examples/pro_micro_rainbow.rs
@@ -28,7 +28,7 @@ use pro_micro_rp2040::{
use smart_leds::{brightness, SmartLedsWrite, RGB8};
use ws2812_pio::Ws2812;
-/// The linker will place this boot block at the start of our program image.
+//// The linker will place this boot block at the start of our program image.
/// We need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
@@ -80,7 +80,7 @@ fn main() -> ! {
25,
pac.PIO0,
&mut pac.RESETS,
- clocks.system_clock.freq(),
+ clocks.peripheral_clock.freq(),
timer.count_down(),
);
diff --git a/rp2040-hal/README.md b/rp2040-hal/README.md
index b5d1a0b..bdc4e66 100644
--- a/rp2040-hal/README.md
+++ b/rp2040-hal/README.md
@@ -8,16 +8,16 @@
rp-hal
- A Rust HAL impl for the RP family of microcontrollers from the Raspberry Pi Foundation
+ High-level Rust drivers for the Raspberry Silicon RP2040 Microcontroller
- Explore the docs »
+ Explore the API docs »
- View Demo
+ View Demos
·
- Report Bug
+ Report a Bug
·
- Request Feature
+ Chat on Matrix
@@ -27,6 +27,7 @@
Table of Contents
+ - Introduction
-
Getting Started
- - Usage
- Roadmap
- Contributing
- License
@@ -43,70 +43,60 @@
+
+## Introduction
+
+This is the `rp2040-hal` package - a library crate of high-level Rust drivers
+for the Raspberry Silicon RP2040 microcontroller, along with a collection of
+non-board specific example programs for you to study. You should use this crate
+in your application if you want to write code for the RP2040 microcontroller.
+The *HAL* in the name standards for *Hardware Abstraction Layer*, and comes from
+the fact that many of the drivers included implement the generic
+hardware-abstraction interfaces defined in the Rust Embedded Working Group's
+[embedded-hal](https://github.com/rust-embedded/embedded-hal) crate.
+
+We also provide a series of *Board Support Package* (BSP) crates, which take
+this HAL crate and pre-configure the pins according to a specific PCB design. If
+you are using on of the supported boards, you should use one of those crates in
+preference, and return here to see documentation about specific peripherals on
+the RP2040 and how to use them. See the `boards` folder in
+https://github.com/rp-rs/rp-hal/ for more details.
+
## Getting Started
-To get a local copy up and running follow these simple steps.
-
-### Prerequisites
-
-* A [Rust](https://www.rust-lang.org/tools/install) toolchain
-
-### Installation
-
-1. Clone the repo or use the crate
-
- ```sh
- git clone https://github.com/rp-rs/rp-hal
- ```
-
- or
-
- ```sh
- cargo install rp2040-hal
- ```
-
-
-## Usage
-
-Use this space to show useful examples of how a project can be used. Additional screenshots, code examples and demos work well in this space. You may also link to more resources.
-
-For more examples, please refer to the [Documentation](https://github.com/rp-rs/rp-hal)
-
-### Run examples
-
-#### UF2
-
-For boards with uf2 flashloaders like the raspberry pi pico. Install [`elf2uf2-rs`](https://github.com/JoNil/elf2uf2-rs):
-
-```sh
-cargo install elf2uf2-rs
-```
-
-Make sure .cargo/config contains the following (it should by default):
+To include this crate in your project, amend your `Cargo.toml` file to include
```toml
-runner = "elf2uf2-rs -d"
+rp2040-hal = "0.3"
```
-**IMPORTANT: Make sure you've put your device into bootloader mode and the drive is showing as mounted before executing the next command.**
+To obtain a copy of the source code (e.g. if you want to propose a bug-fix or
+new feature, or simply to study the code), run:
-```sh
-cargo run --example pico_pwm_blink # Run `cargo run --example` for more examples
+```console
+$ git clone https://github.com/rp-rs/rp-hal.git
```
+For details on how to program an RP2040 microcontroller, see the [top-level
+rp-hal README](https://github.com/rp-rs/rp-hal/).
+
## Roadmap
-NOTE This HAL is under active development. As such, it is likely to remain volatile until a 1.0.0 release.
+NOTE This HAL is under active development. As such, it is likely to remain
+volatile until a 1.0.0 release.
-See the [open issues](https://github.com/rp-rs/rp-hal/issues) for a list of proposed features (and known issues).
+See the [open issues](https://github.com/rp-rs/rp-hal/issues) for a list of
+proposed features (and known issues).
## Contributing
-Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.
+Contributions are what make the open source community such an amazing place to
+be learn, inspire, and create. Any contributions you make are **greatly
+appreciated**.
1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
diff --git a/rp2040-hal/examples/adc.rs b/rp2040-hal/examples/adc.rs
index 7fb720a..88809d1 100644
--- a/rp2040-hal/examples/adc.rs
+++ b/rp2040-hal/examples/adc.rs
@@ -1,40 +1,63 @@
-//! Read ADC samples from the temperature sensor and pin and
-//! output them to the UART on pins 1 and 2 at 9600 baud
+//! # ADC Example
+//!
+//! This application demonstrates how to read ADC samples from the temperature
+//! sensor and pin and output them to the UART on pins 1 and 2 at 9600 baud.
+//!
+//! It may need to be adapted to your particular board layout and/or pin assignment.
+//!
+//! See the `Cargo.toml` file for Copyright and licence details.
+
#![no_std]
#![no_main]
-use core::fmt::Write;
-use cortex_m::prelude::_embedded_hal_adc_OneShot;
+// The macro for our start-up function
use cortex_m_rt::entry;
-use hal::adc::Adc;
-use hal::clocks::init_clocks_and_plls;
-use hal::gpio::{self, Pins};
-use hal::pac;
-use hal::sio::Sio;
-use hal::uart::UartPeripheral;
-use hal::watchdog::Watchdog;
+
+// Ensure we halt the program on panic (if we don't mention this crate it won't
+// be linked)
use panic_halt as _;
+
+// Alias for our HAL crate
use rp2040_hal as hal;
+// Some traits we need
+use core::fmt::Write;
+use embedded_hal::adc::OneShot;
+use embedded_time::fixed_point::FixedPoint;
+use rp2040_hal::clocks::Clock;
+
+// A shorter alias for the Peripheral Access Crate, which provides low-level
+// register access
+use hal::pac;
+
+/// The linker will place this boot block at the start of our program image. We
+/// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
-// External high-speed crystal on the pico board is 12Mhz
-// Adjust if your board has a different frequency
+/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
+/// if your board has a different frequency
const XTAL_FREQ_HZ: u32 = 12_000_000u32;
-const SYS_FREQ_HZ: u32 = hal::pll::common_configs::PLL_SYS_125MHZ.vco_freq.0;
+/// Entry point to our bare-metal application.
+///
+/// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
+/// as soon as all global variables are initialised.
+///
+/// The function configures the RP2040 peripherals, then prints the temperature
+/// in an infinite loop.
#[entry]
fn main() -> ! {
+ // Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap();
let core = pac::CorePeripherals::take().unwrap();
- let mut watchdog = Watchdog::new(pac.WATCHDOG);
- let sio = Sio::new(pac.SIO);
- // External high-speed crystal on the pico board is 12Mhz
+ // Set up the watchdog driver - needed by the clock setup code
+ let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG);
- let clocks = init_clocks_and_plls(
+ // Configure the clocks
+ let clocks = hal::clocks::init_clocks_and_plls(
XTAL_FREQ_HZ,
pac.XOSC,
pac.CLOCKS,
@@ -46,16 +69,23 @@ fn main() -> ! {
.ok()
.unwrap();
- let mut delay = cortex_m::delay::Delay::new(core.SYST, SYS_FREQ_HZ);
+ // The delay object lets us wait for specified amounts of time (in
+ // milliseconds)
+ let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer());
- let pins = Pins::new(
+ // The single-cycle I/O block controls our GPIO pins
+ let sio = hal::sio::Sio::new(pac.SIO);
+
+ // Set the pins to their default state
+ let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
- let mut uart = UartPeripheral::<_, _>::enable(
+ // Create a UART driver
+ let mut uart = hal::uart::UartPeripheral::<_, _>::enable(
pac.UART0,
&mut pac.RESETS,
hal::uart::common_configs::_9600_8_N_1,
@@ -64,14 +94,19 @@ fn main() -> ! {
.unwrap();
// UART TX (characters sent from pico) on pin 1 (GPIO0) and RX (on pin 2 (GPIO1)
- let _tx_pin = pins.gpio0.into_mode::();
- let _rx_pin = pins.gpio1.into_mode::();
+ let _tx_pin = pins.gpio0.into_mode::();
+ let _rx_pin = pins.gpio1.into_mode::();
+
+ // Write to the UART
uart.write_full_blocking(b"ADC example\r\n");
- // Enable adc
- let mut adc = Adc::new(pac.ADC, &mut pac.RESETS);
+
+ // Enable ADC
+ let mut adc = hal::adc::Adc::new(pac.ADC, &mut pac.RESETS);
+
// Enable the temperature sense channel
let mut temperature_sensor = adc.enable_temp_sensor();
- // Configure one of the pins as an ADC input as well.
+
+ // Configure GPIO26 as an ADC input
let mut adc_pin_0 = pins.gpio26.into_floating_input();
loop {
// Read the raw ADC counts from the temperature sensor channel.
@@ -86,3 +121,5 @@ fn main() -> ! {
delay.delay_ms(1000);
}
}
+
+// End of file
diff --git a/rp2040-hal/examples/blinky.rs b/rp2040-hal/examples/blinky.rs
index c7a3806..6cf2f43 100644
--- a/rp2040-hal/examples/blinky.rs
+++ b/rp2040-hal/examples/blinky.rs
@@ -1,38 +1,94 @@
-//! Blinks the LED on a Pico board
+//! # GPIO 'Blinky' Example
//!
-//! This will blink an LED attached to GP25, which is the pin the Pico uses for the on-board LED.
+//! This application demonstrates how to control a GPIO pin on the RP2040.
+//!
+//! It may need to be adapted to your particular board layout and/or pin assignment.
+//!
+//! See the `Cargo.toml` file for Copyright and licence details.
+
#![no_std]
#![no_main]
+// The macro for our start-up function
use cortex_m_rt::entry;
-use embedded_hal::digital::v2::OutputPin;
-use hal::pac;
-use hal::sio::Sio;
+
+// Ensure we halt the program on panic (if we don't mention this crate it won't
+// be linked)
use panic_halt as _;
+
+// Alias for our HAL crate
use rp2040_hal as hal;
+// A shorter alias for the Peripheral Access Crate, which provides low-level
+// register access
+use hal::pac;
+
+// Some traits we need
+use embedded_hal::digital::v2::OutputPin;
+use embedded_time::fixed_point::FixedPoint;
+use rp2040_hal::clocks::Clock;
+
+/// The linker will place this boot block at the start of our program image. We
+// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
+/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
+/// if your board has a different frequency
+const XTAL_FREQ_HZ: u32 = 12_000_000u32;
+
+/// Entry point to our bare-metal application.
+///
+/// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
+/// as soon as all global variables are initialised.
+///
+/// The function configures the RP2040 peripherals, then toggles a GPIO pin in
+/// an infinite loop. If there is an LED connected to that pin, it will blink.
#[entry]
fn main() -> ! {
+ // Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap();
+ let core = pac::CorePeripherals::take().unwrap();
- let sio = Sio::new(pac.SIO);
+ // Set up the watchdog driver - needed by the clock setup code
+ let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG);
+
+ // Configure the clocks
+ let clocks = hal::clocks::init_clocks_and_plls(
+ XTAL_FREQ_HZ,
+ pac.XOSC,
+ pac.CLOCKS,
+ pac.PLL_SYS,
+ pac.PLL_USB,
+ &mut pac.RESETS,
+ &mut watchdog,
+ )
+ .ok()
+ .unwrap();
+
+ let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer());
+
+ // The single-cycle I/O block controls our GPIO pins
+ let sio = hal::sio::Sio::new(pac.SIO);
+
+ // Set the pins to their default state
let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
- let mut led_pin = pins.gpio25.into_push_pull_output();
+ // Configure GPIO25 as an output
+ let mut led_pin = pins.gpio25.into_push_pull_output();
loop {
led_pin.set_high().unwrap();
// TODO: Replace with proper 1s delays once we have clocks working
- cortex_m::asm::delay(500_000);
+ delay.delay_ms(500);
led_pin.set_low().unwrap();
- cortex_m::asm::delay(500_000);
+ delay.delay_ms(500);
}
}
+
+// End of file
diff --git a/rp2040-hal/examples/gpio_in_out.rs b/rp2040-hal/examples/gpio_in_out.rs
index b25e9cb..f2aa738 100644
--- a/rp2040-hal/examples/gpio_in_out.rs
+++ b/rp2040-hal/examples/gpio_in_out.rs
@@ -1,41 +1,95 @@
-//! Toggle LED based on GPIO input
+//! # GPIO 'Blinky' Example
//!
-//! This will control an LED on GP25 based on a button hooked up to GP15. The button should be tied
-//! to ground, as the input pin is pulled high internally by this example. When the button is
-//! pressed, the LED will turn off.
+//! This application demonstrates how to control a GPIO pin on the RP2040.
+//!
+//! It may need to be adapted to your particular board layout and/or pin assignment.
+//!
+//! See the `Cargo.toml` file for Copyright and licence details.
+
#![no_std]
#![no_main]
+// The macro for our start-up function
use cortex_m_rt::entry;
-use embedded_hal::digital::v2::{InputPin, OutputPin};
-use hal::pac;
-use hal::sio::Sio;
+
+// Ensure we halt the program on panic (if we don't mention this crate it won't
+// be linked)
use panic_halt as _;
+
+// Alias for our HAL crate
use rp2040_hal as hal;
+// A shorter alias for the Peripheral Access Crate, which provides low-level
+// register access
+use hal::pac;
+
+// Some traits we need
+use embedded_hal::digital::v2::InputPin;
+use embedded_hal::digital::v2::OutputPin;
+
+/// The linker will place this boot block at the start of our program image. We
+/// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
+/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
+/// if your board has a different frequency
+const XTAL_FREQ_HZ: u32 = 12_000_000u32;
+
+/// Entry point to our bare-metal application.
+///
+/// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
+/// as soon as all global variables are initialised.
+///
+/// The function configures the RP2040 peripherals, then toggles a GPIO pin in
+/// an infinite loop. If there is an LED connected to that pin, it will blink.
#[entry]
fn main() -> ! {
+ // Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap();
- let sio = Sio::new(pac.SIO);
+ // Set up the watchdog driver - needed by the clock setup code
+ let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG);
+
+ // Configure the clocks
+ let _clocks = hal::clocks::init_clocks_and_plls(
+ XTAL_FREQ_HZ,
+ pac.XOSC,
+ pac.CLOCKS,
+ pac.PLL_SYS,
+ pac.PLL_USB,
+ &mut pac.RESETS,
+ &mut watchdog,
+ )
+ .ok()
+ .unwrap();
+
+ // The single-cycle I/O block controls our GPIO pins
+ let sio = hal::sio::Sio::new(pac.SIO);
+
+ // Set the pins to their default state
let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
- let mut led_pin = pins.gpio25.into_push_pull_output();
- let button_pin = pins.gpio23.into_pull_down_input();
+ // Configure GPIO 25 as an output
+ let mut out_pin = pins.gpio25.into_push_pull_output();
+
+ // Configure GPIO 23 as an input
+ let in_pin = pins.gpio23.into_pull_down_input();
+
+ // Output is the opposite of the input
loop {
- if button_pin.is_low().unwrap() {
- led_pin.set_high().unwrap();
+ if in_pin.is_low().unwrap() {
+ out_pin.set_high().unwrap();
} else {
- led_pin.set_low().unwrap();
+ out_pin.set_low().unwrap();
}
}
}
+
+// End of file
diff --git a/rp2040-hal/examples/i2c.rs b/rp2040-hal/examples/i2c.rs
index 18c9f91..8d401fd 100644
--- a/rp2040-hal/examples/i2c.rs
+++ b/rp2040-hal/examples/i2c.rs
@@ -1,49 +1,106 @@
-//! Sends a message using i2c
-#![no_std]
-#![no_main]
-
-use cortex_m_rt::entry;
-use embedded_hal::blocking::i2c::Write;
-use embedded_time::rate::Extensions;
-use hal::gpio::FunctionI2C;
-use hal::i2c::I2C;
-use hal::pac;
-use hal::sio::Sio;
-use panic_halt as _;
-use rp2040_hal as hal;
-
-#[link_section = ".boot2"]
-#[used]
-pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
-
-const SYS_HZ: u32 = 125_000_000_u32;
-
-#[entry]
-fn main() -> ! {
- let mut pac = pac::Peripherals::take().unwrap();
-
- let sio = Sio::new(pac.SIO);
- let pins = hal::gpio::Pins::new(
- pac.IO_BANK0,
- pac.PADS_BANK0,
- sio.gpio_bank0,
- &mut pac.RESETS,
- );
-
- let sda_pin = pins.gpio18.into_mode::();
- let scl_pin = pins.gpio19.into_mode::();
-
- let mut i2c = I2C::i2c1(
- pac.I2C1,
- sda_pin,
- scl_pin,
- 400.kHz(),
- &mut pac.RESETS,
- SYS_HZ.Hz(),
- );
-
- i2c.write(0x2c, &[1, 2, 3]).unwrap();
-
- #[allow(clippy::empty_loop)]
- loop {}
-}
+//! # I²C Example
+//!
+//! This application demonstrates how to talk to I²C devices with an RP2040.
+//!
+//! It may need to be adapted to your particular board layout and/or pin assignment.
+//!
+//! See the `Cargo.toml` file for Copyright and licence details.
+
+#![no_std]
+#![no_main]
+
+// The macro for our start-up function
+use cortex_m_rt::entry;
+
+// Ensure we halt the program on panic (if we don't mention this crate it won't
+// be linked)
+use panic_halt as _;
+
+// Some traits we need
+use embedded_hal::blocking::i2c::Write;
+use embedded_time::rate::Extensions;
+
+// Alias for our HAL crate
+use rp2040_hal as hal;
+
+// A shorter alias for the Peripheral Access Crate, which provides low-level
+// register access
+use hal::pac;
+
+/// The linker will place this boot block at the start of our program image. We
+/// need this to help the ROM bootloader get our code up and running.
+#[link_section = ".boot2"]
+#[used]
+pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
+
+/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
+/// if your board has a different frequency
+const XTAL_FREQ_HZ: u32 = 12_000_000u32;
+
+/// Entry point to our bare-metal application.
+///
+/// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
+/// as soon as all global variables are initialised.
+///
+/// The function configures the RP2040 peripherals, then performs a single I²C
+/// write to a fixed address.
+#[entry]
+fn main() -> ! {
+ let mut pac = pac::Peripherals::take().unwrap();
+
+ // Set up the watchdog driver - needed by the clock setup code
+ let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG);
+
+ // Configure the clocks
+ let clocks = hal::clocks::init_clocks_and_plls(
+ XTAL_FREQ_HZ,
+ pac.XOSC,
+ pac.CLOCKS,
+ pac.PLL_SYS,
+ pac.PLL_USB,
+ &mut pac.RESETS,
+ &mut watchdog,
+ )
+ .ok()
+ .unwrap();
+
+ // The single-cycle I/O block controls our GPIO pins
+ let sio = hal::sio::Sio::new(pac.SIO);
+
+ // Set the pins to their default state
+ let pins = hal::gpio::Pins::new(
+ pac.IO_BANK0,
+ pac.PADS_BANK0,
+ sio.gpio_bank0,
+ &mut pac.RESETS,
+ );
+
+ // Configure two pins as being I²C, not GPIO
+ let sda_pin = pins.gpio18.into_mode::();
+ let scl_pin = pins.gpio19.into_mode::();
+ // let not_an_scl_pin = pins.gpio20.into_mode::();
+
+ // Create the I²C drive, using the two pre-configured pins. This will fail
+ // at compile time if the pins are in the wrong mode, or if this I²C
+ // peripheral isn't available on these pins!
+ let mut i2c = hal::i2c::I2C::i2c1(
+ pac.I2C1,
+ sda_pin,
+ scl_pin, // Try `not_an_scl_pin` here
+ 400.kHz(),
+ &mut pac.RESETS,
+ clocks.peripheral_clock,
+ );
+
+ // Write three bytes to the I²C device with 7-bit address 0x2C
+ i2c.write(0x2c, &[1, 2, 3]).unwrap();
+
+ // Demo finish - just loop until reset
+
+ #[allow(clippy::empty_loop)]
+ loop {
+ // Empty loop
+ }
+}
+
+// End of file
diff --git a/rp2040-hal/examples/lcd_display.rs b/rp2040-hal/examples/lcd_display.rs
index f508c55..bb9fe9c 100644
--- a/rp2040-hal/examples/lcd_display.rs
+++ b/rp2040-hal/examples/lcd_display.rs
@@ -1,26 +1,85 @@
+//! # LCD Display Example
+//!
+//! In this example, the RP2040 is configured to drive a small two-line
+//! alphanumeric LCD using the
+//! [HD44780](https://crates.io/crates/hd44780-driver) driver.
+//!
+//! It drives the LCD by pushing data out of six GPIO pins. It may need to be
+//! adapted to your particular board layout and/or pin assignment.
+//!
+//! See the `Cargo.toml` file for Copyright and licence details.
+
#![no_std]
#![no_main]
+// The macro for our start-up function
use cortex_m_rt::entry;
-use hal::pac;
-use hal::sio::Sio;
-use hd44780_driver as hd44780;
+
+// Ensure we halt the program on panic (if we don't mention this crate it won't
+// be linked)
use panic_halt as _;
+
+// Alias for our HAL crate
use rp2040_hal as hal;
+// Our LCD driver
+use hd44780_driver as hd44780;
+
+// Some traits we need
+use embedded_time::fixed_point::FixedPoint;
+use rp2040_hal::clocks::Clock;
+
+// A shorter alias for the Peripheral Access Crate, which provides low-level
+// register access
+use hal::pac;
+
+/// The linker will place this boot block at the start of our program image. We
+/// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
+/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
+/// if your board has a different frequency
+const XTAL_FREQ_HZ: u32 = 12_000_000u32;
+
+/// Entry point to our bare-metal application.
+///
+/// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
+/// as soon as all global variables are initialised.
+///
+/// The function configures the RP2040 peripherals, writes to the LCD, then goes
+/// to sleep.
#[entry]
fn main() -> ! {
+ // Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap();
let core = pac::CorePeripherals::take().unwrap();
- // AHL bus speed default
- let mut delay_provider = cortex_m::delay::Delay::new(core.SYST, 12_000_000);
+ // Set up the watchdog driver - needed by the clock setup code
+ let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG);
- let sio = Sio::new(pac.SIO);
+ // Configure the clocks
+ let clocks = hal::clocks::init_clocks_and_plls(
+ XTAL_FREQ_HZ,
+ pac.XOSC,
+ pac.CLOCKS,
+ pac.PLL_SYS,
+ pac.PLL_USB,
+ &mut pac.RESETS,
+ &mut watchdog,
+ )
+ .ok()
+ .unwrap();
+
+ // The delay object lets us wait for specified amounts of time (in
+ // milliseconds)
+ let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer());
+
+ // The single-cycle I/O block controls our GPIO pins
+ let sio = hal::sio::Sio::new(pac.SIO);
+
+ // Set the pins to their default state
let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
@@ -28,26 +87,36 @@ fn main() -> ! {
&mut pac.RESETS,
);
- let lcd = hd44780::HD44780::new_4bit(
+ // Create the LCD driver from some GPIO pins
+ let mut lcd = hd44780::HD44780::new_4bit(
pins.gpio16.into_push_pull_output(), // Register Select
pins.gpio17.into_push_pull_output(), // Enable
pins.gpio18.into_push_pull_output(), // d4
pins.gpio19.into_push_pull_output(), // d5
pins.gpio20.into_push_pull_output(), // d6
pins.gpio21.into_push_pull_output(), // d7
- &mut delay_provider,
- );
+ &mut delay,
+ )
+ .unwrap();
- let mut lcd = lcd.unwrap();
+ // Clear the screen
+ lcd.reset(&mut delay).unwrap();
+ lcd.clear(&mut delay).unwrap();
- lcd.reset(&mut delay_provider).unwrap();
- lcd.clear(&mut delay_provider).unwrap();
- lcd.write_str("rp-hal on", &mut delay_provider).unwrap();
- lcd.set_cursor_pos(40, &mut delay_provider).unwrap();
- lcd.set_cursor_visibility(hd44780::Cursor::Visible, &mut delay_provider)
- .unwrap();
- lcd.write_str("HD44780!", &mut delay_provider).unwrap();
+ // Write to the top line
+ lcd.write_str("rp-hal on", &mut delay).unwrap();
+ // Move the cursor
+ lcd.set_cursor_pos(40, &mut delay).unwrap();
+
+ // Write more more text
+ lcd.write_str("HD44780!", &mut delay).unwrap();
+
+ // Do nothing - we're finished
#[allow(clippy::empty_loop)]
- loop {}
+ loop {
+ // Empty loop
+ }
}
+
+// End of file
diff --git a/rp2040-hal/examples/pwm_blink.rs b/rp2040-hal/examples/pwm_blink.rs
index afd194a..ec81a68 100644
--- a/rp2040-hal/examples/pwm_blink.rs
+++ b/rp2040-hal/examples/pwm_blink.rs
@@ -1,43 +1,124 @@
+//! # PWM Blink Example
+//!
+//! If you have an LED connected to pin 25, it will fade the LED using the PWM
+//! peripheral.
+//!
+//! It may need to be adapted to your particular board layout and/or pin assignment.
+//!
+//! See the `Cargo.toml` file for Copyright and licence details.
+
#![no_std]
#![no_main]
+// The macro for our start-up function
use cortex_m_rt::entry;
-use embedded_hal::PwmPin;
-use panic_halt as _;
-use rp2040_hal::{gpio::Pins, pwm::*, sio::Sio};
+// Ensure we halt the program on panic (if we don't mention this crate it won't
+// be linked)
+use panic_halt as _;
+
+// Alias for our HAL crate
+use rp2040_hal as hal;
+
+// Some traits we need
+use embedded_hal::PwmPin;
+use embedded_time::rate::*;
+use rp2040_hal::clocks::Clock;
+
+// A shorter alias for the Peripheral Access Crate, which provides low-level
+// register access
+use hal::pac;
+
+//// The linker will place this boot block at the start of our program image. We
+//// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
+/// The minimum PWM value (i.e. LED brightness) we want
+const LOW: u16 = 0;
+
+/// The maximum PWM value (i.e. LED brightness) we want
+const HIGH: u16 = 25000;
+
+/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
+/// if your board has a different frequency
+const XTAL_FREQ_HZ: u32 = 12_000_000u32;
+
+/// Entry point to our bare-metal application.
+///
+/// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
+/// as soon as all global variables are initialised.
+///
+/// The function configures the RP2040 peripherals, then fades the LED in an
+/// infinite loop.
#[entry]
fn main() -> ! {
- let mut pac = rp2040_pac::Peripherals::take().unwrap();
+ // Grab our singleton objects
+ let mut pac = pac::Peripherals::take().unwrap();
+ let core = pac::CorePeripherals::take().unwrap();
- let sio = Sio::new(pac.SIO);
- let pins = Pins::new(
+ // Set up the watchdog driver - needed by the clock setup code
+ let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG);
+
+ // Configure the clocks
+ //
+ // The default is to generate a 125 MHz system clock
+ let clocks = hal::clocks::init_clocks_and_plls(
+ XTAL_FREQ_HZ,
+ pac.XOSC,
+ pac.CLOCKS,
+ pac.PLL_SYS,
+ pac.PLL_USB,
+ &mut pac.RESETS,
+ &mut watchdog,
+ )
+ .ok()
+ .unwrap();
+
+ // The single-cycle I/O block controls our GPIO pins
+ let sio = hal::sio::Sio::new(pac.SIO);
+
+ // Set the pins up according to their function on this particular board
+ let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
+ // The delay object lets us wait for specified amounts of time (in
+ // milliseconds)
+ let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer());
+
// Init PWMs
- let pwm_slices = Slices::new(pac.PWM, &mut pac.RESETS);
+ let mut pwm_slices = hal::pwm::Slices::new(pac.PWM, &mut pac.RESETS);
// Configure PWM4
- let mut pwm = pwm_slices.pwm4;
+ let pwm = &mut pwm_slices.pwm4;
pwm.set_ph_correct();
pwm.enable();
- // Use B channel (which outputs to GPIO 25)
- let mut channel = pwm.channel_b;
+ // Output channel B on PWM4 to GPIO 25
+ let channel = &mut pwm.channel_b;
channel.output_to(pins.gpio25);
+
+ // Infinite loop, fading LED up and down
loop {
- channel.set_duty(15000);
- // TODO: Replace with proper delays once we have clocks working
- cortex_m::asm::delay(5_000_000);
- channel.set_duty(30000);
- cortex_m::asm::delay(5_000_000);
+ // Ramp brightness up
+ for i in (LOW..=HIGH).skip(100) {
+ delay.delay_us(8);
+ channel.set_duty(i);
+ }
+
+ // Ramp brightness down
+ for i in (LOW..=HIGH).rev().skip(100) {
+ delay.delay_us(8);
+ channel.set_duty(i);
+ }
+
+ delay.delay_ms(500);
}
}
+
+// End of file
diff --git a/rp2040-hal/examples/spi.rs b/rp2040-hal/examples/spi.rs
index e6d0f4f..c363aee 100644
--- a/rp2040-hal/examples/spi.rs
+++ b/rp2040-hal/examples/spi.rs
@@ -1,29 +1,78 @@
-//! Perform ]
+//! # SPI Example
+//!
+//! This application demonstrates how to use the SPI Driver to talk to a remote
+//! SPI device.
+//!
+//!
+//! It may need to be adapted to your particular board layout and/or pin
+//! assignment.
+//!
+//! See the `Cargo.toml` file for Copyright and licence details.
+
#![no_std]
#![no_main]
-use cortex_m::prelude::{
- _embedded_hal_blocking_spi_Transfer, _embedded_hal_blocking_spi_Write,
- _embedded_hal_spi_FullDuplex,
-};
+// The macro for our start-up function
use cortex_m_rt::entry;
-use embedded_hal::spi::MODE_0;
-use embedded_time::rate::Extensions;
-use hal::{gpio::FunctionSpi, pac, sio::Sio, spi::Spi};
+
+// Ensure we halt the program on panic (if we don't mention this crate it won't
+// be linked)
use panic_halt as _;
+
+// Alias for our HAL crate
use rp2040_hal as hal;
+// Some traits we need
+use cortex_m::prelude::*;
+use embedded_time::rate::Extensions;
+use rp2040_hal::clocks::Clock;
+
+// A shorter alias for the Peripheral Access Crate, which provides low-level
+// register access
+use hal::pac;
+
+/// The linker will place this boot block at the start of our program image. We
+/// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
-const SYS_HZ: u32 = 125_000_000_u32;
+/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
+/// if your board has a different frequency
+const XTAL_FREQ_HZ: u32 = 12_000_000u32;
+/// Entry point to our bare-metal application.
+///
+/// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
+/// as soon as all global variables are initialised.
+///
+/// The function configures the RP2040 peripherals, then performs some example
+/// SPI transactions, then goes to sleep.
#[entry]
fn main() -> ! {
+ // Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap();
- let sio = Sio::new(pac.SIO);
+ // Set up the watchdog driver - needed by the clock setup code
+ let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG);
+
+ // Configure the clocks
+ let clocks = hal::clocks::init_clocks_and_plls(
+ XTAL_FREQ_HZ,
+ pac.XOSC,
+ pac.CLOCKS,
+ pac.PLL_SYS,
+ pac.PLL_USB,
+ &mut pac.RESETS,
+ &mut watchdog,
+ )
+ .ok()
+ .unwrap();
+
+ // The single-cycle I/O block controls our GPIO pins
+ let sio = hal::sio::Sio::new(pac.SIO);
+
+ // Set the pins to their default state
let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
@@ -32,19 +81,22 @@ fn main() -> ! {
);
// These are implicitly used by the spi driver if they are in the correct mode
- let _spi_sclk = pins.gpio6.into_mode::();
- let _spi_mosi = pins.gpio7.into_mode::();
- let _spi_miso = pins.gpio4.into_mode::();
- let mut spi = Spi::<_, _, 8>::new(pac.SPI0).init(
+ let _spi_sclk = pins.gpio6.into_mode::();
+ let _spi_mosi = pins.gpio7.into_mode::();
+ let _spi_miso = pins.gpio4.into_mode::();
+ let spi = hal::spi::Spi::<_, _, 8>::new(pac.SPI0);
+
+ // Exchange the uninitialised SPI driver for an initialised one
+ let mut spi = spi.init(
&mut pac.RESETS,
- SYS_HZ.Hz(),
+ clocks.peripheral_clock.freq(),
16_000_000u32.Hz(),
- &MODE_0,
+ &embedded_hal::spi::MODE_0,
);
// Write out 0, ignore return value
- if let Ok(..) = spi.write(&[0]) {
- // Handle success
+ if spi.write(&[0]).is_ok() {
+ // SPI write was succesful
};
// write 50, then check the return
@@ -52,17 +104,17 @@ fn main() -> ! {
match send_success {
Ok(_) => {
// We succeeded, check the read value
- if spi.read().is_ok() {
- // Output our read value
+ if let Ok(_x) = spi.read() {
+ // We got back `x` in exchange for the 0x50 we sent.
};
}
Err(_) => todo!(),
}
- // Do a read+write at the same time.
- // Data in read_write_cache will be replaced with the read data
- let mut read_write_cache: [u8; 4] = [1, 2, 3, 4];
- let transfer_success = spi.transfer(&mut read_write_cache);
+ // Do a read+write at the same time. Data in `buffer` will be replaced with
+ // the data read from the SPI device.
+ let mut buffer: [u8; 4] = [1, 2, 3, 4];
+ let transfer_success = spi.transfer(&mut buffer);
#[allow(clippy::single_match)]
match transfer_success {
Ok(_) => {} // Handle success
@@ -70,5 +122,9 @@ fn main() -> ! {
};
#[allow(clippy::empty_loop)]
- loop {}
+ loop {
+ // Empty loop
+ }
}
+
+// End of file
diff --git a/rp2040-hal/examples/uart.rs b/rp2040-hal/examples/uart.rs
index 27a4710..e20443e 100644
--- a/rp2040-hal/examples/uart.rs
+++ b/rp2040-hal/examples/uart.rs
@@ -1,32 +1,64 @@
-//! Print an incrementing number to UART0 in a loop
+//! # UART Example
+//!
+//! This application demonstrates how to use the UART Driver to talk to a serial
+//! connection.
+//!
+//! It may need to be adapted to your particular board layout and/or pin
+//! assignment.
+//!
+//! See the `Cargo.toml` file for Copyright and licence details.
+
#![no_std]
#![no_main]
-use core::fmt::Write;
+// The macro for our start-up function
use cortex_m_rt::entry;
-use hal::clocks::init_clocks_and_plls;
-use hal::gpio::{self, Pins};
-use hal::pac;
-use hal::sio::Sio;
-use hal::uart::UartPeripheral;
-use hal::watchdog::Watchdog;
+
+// Ensure we halt the program on panic (if we don't mention this crate it won't
+// be linked)
use panic_halt as _;
+
+// Alias for our HAL crate
use rp2040_hal as hal;
+// A shorter alias for the Peripheral Access Crate, which provides low-level
+// register access
+use hal::pac;
+
+// Some traits we need
+use core::fmt::Write;
+use embedded_time::fixed_point::FixedPoint;
+use rp2040_hal::clocks::Clock;
+
+/// The linker will place this boot block at the start of our program image. We
+// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
+/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
+/// if your board has a different frequency
+const XTAL_FREQ_HZ: u32 = 12_000_000u32;
+
+/// Entry point to our bare-metal application.
+///
+/// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
+/// as soon as all global variables are initialised.
+///
+/// The function configures the RP2040 peripherals, then writes to the UART in
+/// an inifinite loop.
#[entry]
fn main() -> ! {
+ // Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap();
- let mut watchdog = Watchdog::new(pac.WATCHDOG);
- let sio = Sio::new(pac.SIO);
+ let core = pac::CorePeripherals::take().unwrap();
- // External high-speed crystal on the pico board is 12Mhz
- let external_xtal_freq_hz = 12_000_000u32;
- let clocks = init_clocks_and_plls(
- external_xtal_freq_hz,
+ // Set up the watchdog driver - needed by the clock setup code
+ let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG);
+
+ // Configure the clocks
+ let clocks = hal::clocks::init_clocks_and_plls(
+ XTAL_FREQ_HZ,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
@@ -37,14 +69,20 @@ fn main() -> ! {
.ok()
.unwrap();
- let pins = Pins::new(
+ let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer());
+
+ // The single-cycle I/O block controls our GPIO pins
+ let sio = hal::sio::Sio::new(pac.SIO);
+
+ // Set the pins to their default state
+ let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
- let mut uart = UartPeripheral::<_, _>::enable(
+ let mut uart = hal::uart::UartPeripheral::<_, _>::enable(
pac.UART0,
&mut pac.RESETS,
hal::uart::common_configs::_9600_8_N_1,
@@ -52,16 +90,19 @@ fn main() -> ! {
)
.unwrap();
- // UART TX (characters sent from pico) on pin 1 (GPIO0) and RX (on pin 2 (GPIO1)
- let _tx_pin = pins.gpio0.into_mode::();
- let _rx_pin = pins.gpio1.into_mode::();
+ // UART TX (characters sent from RP2040) on pin 1 (GPIO0)
+ let _tx_pin = pins.gpio0.into_mode::();
+ // UART RX (characters reveived by RP2040) on pin 2 (GPIO1)
+ let _rx_pin = pins.gpio1.into_mode::();
uart.write_full_blocking(b"UART example\r\n");
let mut value = 0u32;
loop {
writeln!(uart, "value: {:02}\r", value).unwrap();
- cortex_m::asm::delay(10_000_000);
+ delay.delay_ms(1000);
value += 1
}
}
+
+// End of file
diff --git a/rp2040-hal/examples/watchdog.rs b/rp2040-hal/examples/watchdog.rs
index f230f8b..41aae21 100644
--- a/rp2040-hal/examples/watchdog.rs
+++ b/rp2040-hal/examples/watchdog.rs
@@ -1,37 +1,65 @@
-//! How to use the watchdog peripheral to reset the system in case something takes too long
+//! # Watchdog Example
+//!
+//! This application demonstrates how to use the RP2040 Watchdog.
+//!
+//! It may need to be adapted to your particular board layout and/or pin assignment.
+//!
+//! See the `Cargo.toml` file for Copyright and licence details.
+
#![no_std]
#![no_main]
-use cortex_m::prelude::{_embedded_hal_watchdog_Watchdog, _embedded_hal_watchdog_WatchdogEnable};
+// The macro for our start-up function
use cortex_m_rt::entry;
-use embedded_hal::digital::v2::OutputPin;
-use embedded_time::duration::units::*;
-use embedded_time::fixed_point::FixedPoint;
-use hal::clocks::{init_clocks_and_plls, Clock};
-use hal::gpio::Pins;
-use hal::pac;
-use hal::sio::Sio;
-use hal::watchdog::Watchdog;
+
+// Ensure we halt the program on panic (if we don't mention this crate it won't
+// be linked)
use panic_halt as _;
+
+// Alias for our HAL crate
use rp2040_hal as hal;
+// A shorter alias for the Peripheral Access Crate, which provides low-level
+// register access
+use hal::pac;
+
+// Some traits we need
+use embedded_hal::digital::v2::OutputPin;
+use embedded_hal::watchdog::{Watchdog, WatchdogEnable};
+use embedded_time::duration::Extensions;
+use embedded_time::fixed_point::FixedPoint;
+use rp2040_hal::clocks::Clock;
+
+/// The linker will place this boot block at the start of our program image. We
+// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
-// External high-speed crystal on the pico board is 12Mhz
-// Adjust for your board if this isn't the same
-const EXTERNAL_XTAL_FREQ_HZ: u32 = 12_000_000;
+/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
+/// if your board has a different frequency
+const XTAL_FREQ_HZ: u32 = 12_000_000u32;
+/// Entry point to our bare-metal application.
+///
+/// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
+/// as soon as all global variables are initialised.
+///
+/// The function configures the RP2040 peripherals, then toggles a GPIO pin in
+/// an infinite loop. After a period of time, the watchdog will kick in to reset
+/// the CPU.
#[entry]
fn main() -> ! {
+ // Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap();
- let cp = pac::CorePeripherals::take().unwrap();
- let mut watchdog = Watchdog::new(pac.WATCHDOG);
- let sio = Sio::new(pac.SIO);
+ let core = pac::CorePeripherals::take().unwrap();
- let clocks = init_clocks_and_plls(
- EXTERNAL_XTAL_FREQ_HZ,
+ // Set up the watchdog driver - needed by the clock setup code
+ let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG);
+
+ // Configure the clocks
+ let clocks = hal::clocks::init_clocks_and_plls(
+ XTAL_FREQ_HZ,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
@@ -42,16 +70,19 @@ fn main() -> ! {
.ok()
.unwrap();
- let pins = Pins::new(
+ let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().integer());
+
+ // The single-cycle I/O block controls our GPIO pins
+ let sio = hal::sio::Sio::new(pac.SIO);
+
+ // Set the pins to their default state
+ let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
- // We need to accurately delay to give feedback that the watchdog is working correctly
- let mut delay = cortex_m::delay::Delay::new(cp.SYST, clocks.system_clock.freq().integer());
-
// Configure an LED so we can show the current state of the watchdog
let mut led_pin = pins.gpio25.into_push_pull_output();
@@ -60,7 +91,7 @@ fn main() -> ! {
delay.delay_ms(2000);
// Set to watchdog to reset if it's not reloaded within 1.05 seconds, and start it
- watchdog.start(1_050_000.microseconds());
+ watchdog.start(1_050_000u32.microseconds());
// Blink once a second for 5 seconds, refreshing the watchdog timer once a second to avoid a reset
for _ in 1..=5 {
@@ -80,3 +111,5 @@ fn main() -> ! {
delay.delay_ms(100);
}
}
+
+// End of file