Merge pull request #137 from 42-technology-ltd/ensure-hal-examples-non-board-specific

Working on README and examples
This commit is contained in:
Jonathan Pallant 2021-09-28 10:46:42 +01:00 committed by GitHub
commit da89888ccb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 925 additions and 294 deletions

View file

@ -10,3 +10,4 @@ rustflags = [
"-C", "no-vectorize-loops", "-C", "no-vectorize-loops",
] ]
runner = "elf2uf2-rs -d" runner = "elf2uf2-rs -d"
# runner = "probe-run-rp --chip RP2040"

188
README.md
View file

@ -8,26 +8,26 @@
<h3 align="center">rp-hal</h3> <h3 align="center">rp-hal</h3>
<p align="center"> <p align="center">
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
<br /> <br />
<a href="https://github.com/rp-rs/rp-hal"><strong>Explore the docs »</strong></a> <a href="https://docs.rs/rp2040-hal"><strong>Explore the API docs »</strong></a>
<br /> <br />
<br /> <br />
<a href="https://github.com/rp-rs/rp-hal">View Demo</a> <a href="https://github.com/rp-rs/rp-hal/tree/main/boards/pico/examples">View Demos</a>
· ·
<a href="https://github.com/rp-rs/rp-hal/issues">Report Bug</a> <a href="https://github.com/rp-rs/rp-hal/issues">Report a Bug</a>
· ·
<a href="https://github.com/rp-rs/rp-hal/issues">Request Feature</a> <a href="https://matrix.to/#/#rp-rs:matrix.org">Chat on Matrix</a>
</p> </p>
</p> </p>
<!-- TABLE OF CONTENTS --> <!-- TABLE OF CONTENTS -->
<details open="open"> <details open="open">
<summary><h2 style="display: inline-block">Table of Contents</h2></summary> <summary><h2 style="display: inline-block">Table of Contents</h2></summary>
<ol> <ol>
<li><a href="#packages">Packages</a></li> <li><a href="#gettting_started">Getting Started</a></li>
<li><a href="#programming">Programming</a></li>
<li><a href="#roadmap">Roadmap</a></li> <li><a href="#roadmap">Roadmap</a></li>
<li><a href="#contributing">Contributing</a></li> <li><a href="#contributing">Contributing</a></li>
<li><a href="#license">License</a></li> <li><a href="#license">License</a></li>
@ -37,6 +37,45 @@
</details> </details>
<!-- GETTING STARTED --> <!-- GETTING STARTED -->
## 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 ## Packages
This git repository is organised as a [Cargo Workspace]. 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] depend on multiple _BSP_ crates; you have to pick one, or use [Cargo Features]
to select one at build time. 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] [Cargo Workspace]: https://doc.rust-lang.org/cargo/reference/workspaces.html]
[Embedded HAL]: https://github.com/rust-embedded/embedded-hal [Embedded HAL]: https://github.com/rust-embedded/embedded-hal
[Cargo Features]: https://doc.rust-lang.org/cargo/reference/features.html [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 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). Support Package (see later on).
The crate provides high-level drivers for the RP2040's internal peripherals, 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. particular board.
[rp2040-hal]: https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal [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] ### [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 [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 [pro_micro_rp2040]: https://github.com/rp-rs/rp-hal/tree/main/boards/pro_micro_rp2040
<!-- PROGRAMMING -->
## 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 --> <!-- ROADMAP -->
## Roadmap ## 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).
<!-- CONTRIBUTING --> <!-- CONTRIBUTING -->
@ -195,9 +352,8 @@ under these terms.
<!-- CONTACT --> <!-- CONTACT -->
## Contact ## Contact
Project Link: [https://github.com/rp-rs/rp-hal/issues](https://github.com/rp-rs/rp-hal/issues) Raise an issue: [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) Chat to us on Matrix: [#rp-rs:matrix.org](https://matrix.to/#/#rp-rs:matrix.org)
<!-- ACKNOWLEDGEMENTS --> <!-- ACKNOWLEDGEMENTS -->
## Acknowledgements ## Acknowledgements

View file

@ -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://github.com/rp-rs/rp-hal/tree/main/boards/adafruit_macropad
[Adafruit Macropad]: https://www.adafruit.com/product/5128 [Adafruit Macropad]: https://www.adafruit.com/product/5128
[rp2040-hal]: https://github.com/rp-rs/rp-hal/tree/main/rp2040-hal [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 ## Using

View file

@ -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 [Adafruit Feather RP2040]: https://www.adafruit.com/product/4884
[feather_rp2040]: https://github.com/rp-rs/rp-hal/tree/main/boards/feather_rp2040 [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 [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 ## Using

View file

@ -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/ [Raspberry Pi Pico]: https://www.raspberrypi.org/products/raspberry-pi-pico/
[pico]: https://github.com/rp-rs/rp-hal/tree/main/boards/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 [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 ## Using

View file

@ -34,8 +34,8 @@ use pico::hal::pac;
// higher-level drivers. // higher-level drivers.
use pico::hal; use pico::hal;
/// The linker will place this boot block at the start of our program image. We //// 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. //// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
@ -58,7 +58,7 @@ fn main() -> ! {
// Configure the clocks // 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( let clocks = hal::clocks::init_clocks_and_plls(
pico::XOSC_CRYSTAL_FREQ, pico::XOSC_CRYSTAL_FREQ,
pac.XOSC, pac.XOSC,

View file

@ -47,7 +47,7 @@ fn main() -> ! {
// Configure the clocks // 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( let _clocks = hal::clocks::init_clocks_and_plls(
pico::XOSC_CRYSTAL_FREQ, pico::XOSC_CRYSTAL_FREQ,
pac.XOSC, pac.XOSC,

View file

@ -30,8 +30,8 @@ use pico::hal::pac;
// higher-level drivers. // higher-level drivers.
use pico::hal; use pico::hal;
/// The linker will place this boot block at the start of our program image. We //// 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. //// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;

View file

@ -34,8 +34,8 @@ use pico::hal::pac;
// higher-level drivers. // higher-level drivers.
use pico::hal; use pico::hal;
/// The linker will place this boot block at the start of our program image. We //// 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. //// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
@ -64,7 +64,7 @@ fn main() -> ! {
// Configure the clocks // 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( let clocks = hal::clocks::init_clocks_and_plls(
pico::XOSC_CRYSTAL_FREQ, pico::XOSC_CRYSTAL_FREQ,
pac.XOSC, pac.XOSC,

View file

@ -33,8 +33,8 @@ use usb_device::{class_prelude::*, prelude::*};
// USB Communications Class Device support // USB Communications Class Device support
use usbd_serial::SerialPort; use usbd_serial::SerialPort;
/// The linker will place this boot block at the start of our program image. We //// 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. //// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
@ -56,7 +56,7 @@ fn main() -> ! {
// Configure the clocks // 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( let clocks = hal::clocks::init_clocks_and_plls(
pico::XOSC_CRYSTAL_FREQ, pico::XOSC_CRYSTAL_FREQ,
pac.XOSC, pac.XOSC,

View file

@ -45,8 +45,8 @@ use usb_device::{class_prelude::*, prelude::*};
// USB Communications Class Device support // USB Communications Class Device support
use usbd_serial::SerialPort; use usbd_serial::SerialPort;
/// The linker will place this boot block at the start of our program image. We //// 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. //// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
@ -78,7 +78,7 @@ fn main() -> ! {
// Configure the clocks // 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( let clocks = hal::clocks::init_clocks_and_plls(
pico::XOSC_CRYSTAL_FREQ, pico::XOSC_CRYSTAL_FREQ,
pac.XOSC, pac.XOSC,

View file

@ -44,8 +44,8 @@ use usbd_hid::descriptor::generator_prelude::*;
use usbd_hid::descriptor::MouseReport; use usbd_hid::descriptor::MouseReport;
use usbd_hid::hid_class::HIDClass; use usbd_hid::hid_class::HIDClass;
/// The linker will place this boot block at the start of our program image. We //// 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. //// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
@ -76,7 +76,7 @@ fn main() -> ! {
// Configure the clocks // 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( let clocks = hal::clocks::init_clocks_and_plls(
pico::XOSC_CRYSTAL_FREQ, pico::XOSC_CRYSTAL_FREQ,
pac.XOSC, pac.XOSC,

View file

@ -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 [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 [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 [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 ## Using

View file

@ -34,8 +34,8 @@ use pico_lipo_16_mb::hal::pac;
// higher-level drivers. // higher-level drivers.
use pico_lipo_16_mb::hal; use pico_lipo_16_mb::hal;
/// The linker will place this boot block at the start of our program image. We //// 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. //// need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
@ -58,7 +58,7 @@ fn main() -> ! {
// Configure the clocks // 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( let clocks = hal::clocks::init_clocks_and_plls(
pico_lipo_16_mb::XOSC_CRYSTAL_FREQ, pico_lipo_16_mb::XOSC_CRYSTAL_FREQ,
pac.XOSC, pac.XOSC,

View file

@ -1,7 +1,7 @@
# [pro_micro_rp2040] - Board Support for the [Sparkfun Pro Micro RP2040] # [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 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 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. 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 [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 [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 [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 ## Using

View file

@ -28,7 +28,7 @@ use pro_micro_rp2040::{
use smart_leds::{brightness, SmartLedsWrite, RGB8}; use smart_leds::{brightness, SmartLedsWrite, RGB8};
use ws2812_pio::Ws2812; 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. /// We need this to help the ROM bootloader get our code up and running.
#[link_section = ".boot2"] #[link_section = ".boot2"]
#[used] #[used]
@ -80,7 +80,7 @@ fn main() -> ! {
25, 25,
pac.PIO0, pac.PIO0,
&mut pac.RESETS, &mut pac.RESETS,
clocks.system_clock.freq(), clocks.peripheral_clock.freq(),
timer.count_down(), timer.count_down(),
); );

View file

@ -8,16 +8,16 @@
<h3 align="center">rp-hal</h3> <h3 align="center">rp-hal</h3>
<p align="center"> <p align="center">
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
<br /> <br />
<a href="https://github.com/rp-rs/rp-hal"><strong>Explore the docs »</strong></a> <a href="https://docs.rs/rp2040-hal"><strong>Explore the API docs »</strong></a>
<br /> <br />
<br /> <br />
<a href="https://github.com/rp-rs/rp-hal">View Demo</a> <a href="https://github.com/rp-rs/rp-hal/tree/main/boards/pico/examples">View Demos</a>
· ·
<a href="https://github.com/rp-rs/rp-hal/issues">Report Bug</a> <a href="https://github.com/rp-rs/rp-hal/issues">Report a Bug</a>
· ·
<a href="https://github.com/rp-rs/rp-hal/issues">Request Feature</a> <a href="https://matrix.to/#/#rp-rs:matrix.org">Chat on Matrix</a>
</p> </p>
</p> </p>
@ -27,6 +27,7 @@
<details open="open"> <details open="open">
<summary><h2 style="display: inline-block">Table of Contents</h2></summary> <summary><h2 style="display: inline-block">Table of Contents</h2></summary>
<ol> <ol>
<li><a href="#introduction">Introduction</a></li>
<li> <li>
<a href="#getting-started">Getting Started</a> <a href="#getting-started">Getting Started</a>
<ul> <ul>
@ -34,7 +35,6 @@
<li><a href="#installation">Installation</a></li> <li><a href="#installation">Installation</a></li>
</ul> </ul>
</li> </li>
<li><a href="#usage">Usage</a></li>
<li><a href="#roadmap">Roadmap</a></li> <li><a href="#roadmap">Roadmap</a></li>
<li><a href="#contributing">Contributing</a></li> <li><a href="#contributing">Contributing</a></li>
<li><a href="#license">License</a></li> <li><a href="#license">License</a></li>
@ -43,70 +43,60 @@
</ol> </ol>
</details> </details>
<!-- INTRODUCTION -->
## 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 --> <!-- GETTING STARTED -->
## Getting Started ## Getting Started
To get a local copy up and running follow these simple steps. To include this crate in your project, amend your `Cargo.toml` file to include
### 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 EXAMPLES -->
## 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):
```toml ```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 ```console
cargo run --example pico_pwm_blink # Run `cargo run --example` for more examples $ 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 --> <!-- ROADMAP -->
## Roadmap ## 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 --> <!-- CONTRIBUTING -->
## Contributing ## 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 1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)

View file

@ -1,40 +1,63 @@
//! Read ADC samples from the temperature sensor and pin and //! # ADC Example
//! output them to the UART on pins 1 and 2 at 9600 baud //!
//! 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_std]
#![no_main] #![no_main]
use core::fmt::Write; // The macro for our start-up function
use cortex_m::prelude::_embedded_hal_adc_OneShot;
use cortex_m_rt::entry; use cortex_m_rt::entry;
use hal::adc::Adc;
use hal::clocks::init_clocks_and_plls; // Ensure we halt the program on panic (if we don't mention this crate it won't
use hal::gpio::{self, Pins}; // be linked)
use hal::pac;
use hal::sio::Sio;
use hal::uart::UartPeripheral;
use hal::watchdog::Watchdog;
use panic_halt as _; use panic_halt as _;
// Alias for our HAL crate
use rp2040_hal as hal; 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"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
// External high-speed crystal on the pico board is 12Mhz /// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
// Adjust if your board has a different frequency /// if your board has a different frequency
const XTAL_FREQ_HZ: u32 = 12_000_000u32; 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] #[entry]
fn main() -> ! { fn main() -> ! {
// Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap(); let mut pac = pac::Peripherals::take().unwrap();
let core = pac::CorePeripherals::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, XTAL_FREQ_HZ,
pac.XOSC, pac.XOSC,
pac.CLOCKS, pac.CLOCKS,
@ -46,16 +69,23 @@ fn main() -> ! {
.ok() .ok()
.unwrap(); .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.IO_BANK0,
pac.PADS_BANK0, pac.PADS_BANK0,
sio.gpio_bank0, sio.gpio_bank0,
&mut pac.RESETS, &mut pac.RESETS,
); );
let mut uart = UartPeripheral::<_, _>::enable( // Create a UART driver
let mut uart = hal::uart::UartPeripheral::<_, _>::enable(
pac.UART0, pac.UART0,
&mut pac.RESETS, &mut pac.RESETS,
hal::uart::common_configs::_9600_8_N_1, hal::uart::common_configs::_9600_8_N_1,
@ -64,14 +94,19 @@ fn main() -> ! {
.unwrap(); .unwrap();
// UART TX (characters sent from pico) on pin 1 (GPIO0) and RX (on pin 2 (GPIO1) // UART TX (characters sent from pico) on pin 1 (GPIO0) and RX (on pin 2 (GPIO1)
let _tx_pin = pins.gpio0.into_mode::<gpio::FunctionUart>(); let _tx_pin = pins.gpio0.into_mode::<hal::gpio::FunctionUart>();
let _rx_pin = pins.gpio1.into_mode::<gpio::FunctionUart>(); let _rx_pin = pins.gpio1.into_mode::<hal::gpio::FunctionUart>();
// Write to the UART
uart.write_full_blocking(b"ADC example\r\n"); 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 // Enable the temperature sense channel
let mut temperature_sensor = adc.enable_temp_sensor(); 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(); let mut adc_pin_0 = pins.gpio26.into_floating_input();
loop { loop {
// Read the raw ADC counts from the temperature sensor channel. // Read the raw ADC counts from the temperature sensor channel.
@ -86,3 +121,5 @@ fn main() -> ! {
delay.delay_ms(1000); delay.delay_ms(1000);
} }
} }
// End of file

View file

@ -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_std]
#![no_main] #![no_main]
// The macro for our start-up function
use cortex_m_rt::entry; use cortex_m_rt::entry;
use embedded_hal::digital::v2::OutputPin;
use hal::pac; // Ensure we halt the program on panic (if we don't mention this crate it won't
use hal::sio::Sio; // be linked)
use panic_halt as _; use panic_halt as _;
// Alias for our HAL crate
use rp2040_hal as hal; 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"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; 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] #[entry]
fn main() -> ! { fn main() -> ! {
// Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap(); 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( let pins = hal::gpio::Pins::new(
pac.IO_BANK0, pac.IO_BANK0,
pac.PADS_BANK0, pac.PADS_BANK0,
sio.gpio_bank0, sio.gpio_bank0,
&mut pac.RESETS, &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 { loop {
led_pin.set_high().unwrap(); led_pin.set_high().unwrap();
// TODO: Replace with proper 1s delays once we have clocks working // 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(); led_pin.set_low().unwrap();
cortex_m::asm::delay(500_000); delay.delay_ms(500);
} }
} }
// End of file

View file

@ -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 //! This application demonstrates how to control a GPIO pin on the RP2040.
//! to ground, as the input pin is pulled high internally by this example. When the button is //!
//! pressed, the LED will turn off. //! 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_std]
#![no_main] #![no_main]
// The macro for our start-up function
use cortex_m_rt::entry; use cortex_m_rt::entry;
use embedded_hal::digital::v2::{InputPin, OutputPin};
use hal::pac; // Ensure we halt the program on panic (if we don't mention this crate it won't
use hal::sio::Sio; // be linked)
use panic_halt as _; use panic_halt as _;
// Alias for our HAL crate
use rp2040_hal as hal; 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"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; 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] #[entry]
fn main() -> ! { fn main() -> ! {
// Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap(); 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( let pins = hal::gpio::Pins::new(
pac.IO_BANK0, pac.IO_BANK0,
pac.PADS_BANK0, pac.PADS_BANK0,
sio.gpio_bank0, sio.gpio_bank0,
&mut pac.RESETS, &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 { loop {
if button_pin.is_low().unwrap() { if in_pin.is_low().unwrap() {
led_pin.set_high().unwrap(); out_pin.set_high().unwrap();
} else { } else {
led_pin.set_low().unwrap(); out_pin.set_low().unwrap();
} }
} }
} }
// End of file

View file

@ -1,28 +1,73 @@
//! Sends a message using i2c //! # 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_std]
#![no_main] #![no_main]
// The macro for our start-up function
use cortex_m_rt::entry; 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_hal::blocking::i2c::Write;
use embedded_time::rate::Extensions; use embedded_time::rate::Extensions;
use hal::gpio::FunctionI2C;
use hal::i2c::I2C; // Alias for our HAL crate
use hal::pac;
use hal::sio::Sio;
use panic_halt as _;
use rp2040_hal as hal; 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"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; 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 a single I²C
/// write to a fixed address.
#[entry] #[entry]
fn main() -> ! { fn main() -> ! {
let mut pac = pac::Peripherals::take().unwrap(); 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( let pins = hal::gpio::Pins::new(
pac.IO_BANK0, pac.IO_BANK0,
pac.PADS_BANK0, pac.PADS_BANK0,
@ -30,20 +75,32 @@ fn main() -> ! {
&mut pac.RESETS, &mut pac.RESETS,
); );
let sda_pin = pins.gpio18.into_mode::<FunctionI2C>(); // Configure two pins as being I²C, not GPIO
let scl_pin = pins.gpio19.into_mode::<FunctionI2C>(); let sda_pin = pins.gpio18.into_mode::<hal::gpio::FunctionI2C>();
let scl_pin = pins.gpio19.into_mode::<hal::gpio::FunctionI2C>();
// let not_an_scl_pin = pins.gpio20.into_mode::<hal::gpio::FunctionI2C>();
let mut i2c = I2C::i2c1( // 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, pac.I2C1,
sda_pin, sda_pin,
scl_pin, scl_pin, // Try `not_an_scl_pin` here
400.kHz(), 400.kHz(),
&mut pac.RESETS, &mut pac.RESETS,
SYS_HZ.Hz(), clocks.peripheral_clock,
); );
// Write three bytes to the I²C device with 7-bit address 0x2C
i2c.write(0x2c, &[1, 2, 3]).unwrap(); i2c.write(0x2c, &[1, 2, 3]).unwrap();
// Demo finish - just loop until reset
#[allow(clippy::empty_loop)] #[allow(clippy::empty_loop)]
loop {} loop {
// Empty loop
}
} }
// End of file

View file

@ -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_std]
#![no_main] #![no_main]
// The macro for our start-up function
use cortex_m_rt::entry; use cortex_m_rt::entry;
use hal::pac;
use hal::sio::Sio; // Ensure we halt the program on panic (if we don't mention this crate it won't
use hd44780_driver as hd44780; // be linked)
use panic_halt as _; use panic_halt as _;
// Alias for our HAL crate
use rp2040_hal as hal; 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"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; 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] #[entry]
fn main() -> ! { fn main() -> ! {
// Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap(); let mut pac = pac::Peripherals::take().unwrap();
let core = pac::CorePeripherals::take().unwrap(); let core = pac::CorePeripherals::take().unwrap();
// AHL bus speed default // Set up the watchdog driver - needed by the clock setup code
let mut delay_provider = cortex_m::delay::Delay::new(core.SYST, 12_000_000); 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( let pins = hal::gpio::Pins::new(
pac.IO_BANK0, pac.IO_BANK0,
pac.PADS_BANK0, pac.PADS_BANK0,
@ -28,26 +87,36 @@ fn main() -> ! {
&mut pac.RESETS, &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.gpio16.into_push_pull_output(), // Register Select
pins.gpio17.into_push_pull_output(), // Enable pins.gpio17.into_push_pull_output(), // Enable
pins.gpio18.into_push_pull_output(), // d4 pins.gpio18.into_push_pull_output(), // d4
pins.gpio19.into_push_pull_output(), // d5 pins.gpio19.into_push_pull_output(), // d5
pins.gpio20.into_push_pull_output(), // d6 pins.gpio20.into_push_pull_output(), // d6
pins.gpio21.into_push_pull_output(), // d7 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(); // Write to the top line
lcd.clear(&mut delay_provider).unwrap(); lcd.write_str("rp-hal on", &mut delay).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();
// 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)] #[allow(clippy::empty_loop)]
loop {} loop {
// Empty loop
}
} }
// End of file

View file

@ -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_std]
#![no_main] #![no_main]
// The macro for our start-up function
use cortex_m_rt::entry; 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"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; 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] #[entry]
fn main() -> ! { 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); // Set up the watchdog driver - needed by the clock setup code
let pins = Pins::new( 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.IO_BANK0,
pac.PADS_BANK0, pac.PADS_BANK0,
sio.gpio_bank0, sio.gpio_bank0,
&mut pac.RESETS, &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 // 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 // Configure PWM4
let mut pwm = pwm_slices.pwm4; let pwm = &mut pwm_slices.pwm4;
pwm.set_ph_correct(); pwm.set_ph_correct();
pwm.enable(); pwm.enable();
// Use B channel (which outputs to GPIO 25) // Output channel B on PWM4 to GPIO 25
let mut channel = pwm.channel_b; let channel = &mut pwm.channel_b;
channel.output_to(pins.gpio25); channel.output_to(pins.gpio25);
// Infinite loop, fading LED up and down
loop { loop {
channel.set_duty(15000); // Ramp brightness up
// TODO: Replace with proper delays once we have clocks working for i in (LOW..=HIGH).skip(100) {
cortex_m::asm::delay(5_000_000); delay.delay_us(8);
channel.set_duty(30000); channel.set_duty(i);
cortex_m::asm::delay(5_000_000); }
// 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

View file

@ -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_std]
#![no_main] #![no_main]
use cortex_m::prelude::{ // The macro for our start-up function
_embedded_hal_blocking_spi_Transfer, _embedded_hal_blocking_spi_Write,
_embedded_hal_spi_FullDuplex,
};
use cortex_m_rt::entry; use cortex_m_rt::entry;
use embedded_hal::spi::MODE_0;
use embedded_time::rate::Extensions; // Ensure we halt the program on panic (if we don't mention this crate it won't
use hal::{gpio::FunctionSpi, pac, sio::Sio, spi::Spi}; // be linked)
use panic_halt as _; use panic_halt as _;
// Alias for our HAL crate
use rp2040_hal as hal; 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"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; 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] #[entry]
fn main() -> ! { fn main() -> ! {
// Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap(); 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( let pins = hal::gpio::Pins::new(
pac.IO_BANK0, pac.IO_BANK0,
pac.PADS_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 // These are implicitly used by the spi driver if they are in the correct mode
let _spi_sclk = pins.gpio6.into_mode::<FunctionSpi>(); let _spi_sclk = pins.gpio6.into_mode::<hal::gpio::FunctionSpi>();
let _spi_mosi = pins.gpio7.into_mode::<FunctionSpi>(); let _spi_mosi = pins.gpio7.into_mode::<hal::gpio::FunctionSpi>();
let _spi_miso = pins.gpio4.into_mode::<FunctionSpi>(); let _spi_miso = pins.gpio4.into_mode::<hal::gpio::FunctionSpi>();
let mut spi = Spi::<_, _, 8>::new(pac.SPI0).init( 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, &mut pac.RESETS,
SYS_HZ.Hz(), clocks.peripheral_clock.freq(),
16_000_000u32.Hz(), 16_000_000u32.Hz(),
&MODE_0, &embedded_hal::spi::MODE_0,
); );
// Write out 0, ignore return value // Write out 0, ignore return value
if let Ok(..) = spi.write(&[0]) { if spi.write(&[0]).is_ok() {
// Handle success // SPI write was succesful
}; };
// write 50, then check the return // write 50, then check the return
@ -52,17 +104,17 @@ fn main() -> ! {
match send_success { match send_success {
Ok(_) => { Ok(_) => {
// We succeeded, check the read value // We succeeded, check the read value
if spi.read().is_ok() { if let Ok(_x) = spi.read() {
// Output our read value // We got back `x` in exchange for the 0x50 we sent.
}; };
} }
Err(_) => todo!(), Err(_) => todo!(),
} }
// Do a read+write at the same time. // Do a read+write at the same time. Data in `buffer` will be replaced with
// Data in read_write_cache will be replaced with the read data // the data read from the SPI device.
let mut read_write_cache: [u8; 4] = [1, 2, 3, 4]; let mut buffer: [u8; 4] = [1, 2, 3, 4];
let transfer_success = spi.transfer(&mut read_write_cache); let transfer_success = spi.transfer(&mut buffer);
#[allow(clippy::single_match)] #[allow(clippy::single_match)]
match transfer_success { match transfer_success {
Ok(_) => {} // Handle success Ok(_) => {} // Handle success
@ -70,5 +122,9 @@ fn main() -> ! {
}; };
#[allow(clippy::empty_loop)] #[allow(clippy::empty_loop)]
loop {} loop {
// Empty loop
}
} }
// End of file

View file

@ -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_std]
#![no_main] #![no_main]
use core::fmt::Write; // The macro for our start-up function
use cortex_m_rt::entry; use cortex_m_rt::entry;
use hal::clocks::init_clocks_and_plls;
use hal::gpio::{self, Pins}; // Ensure we halt the program on panic (if we don't mention this crate it won't
use hal::pac; // be linked)
use hal::sio::Sio;
use hal::uart::UartPeripheral;
use hal::watchdog::Watchdog;
use panic_halt as _; use panic_halt as _;
// Alias for our HAL crate
use rp2040_hal as hal; 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"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; 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] #[entry]
fn main() -> ! { fn main() -> ! {
// Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap(); let mut pac = pac::Peripherals::take().unwrap();
let mut watchdog = Watchdog::new(pac.WATCHDOG); let core = pac::CorePeripherals::take().unwrap();
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 external_xtal_freq_hz = 12_000_000u32; let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG);
let clocks = init_clocks_and_plls(
external_xtal_freq_hz, // Configure the clocks
let clocks = hal::clocks::init_clocks_and_plls(
XTAL_FREQ_HZ,
pac.XOSC, pac.XOSC,
pac.CLOCKS, pac.CLOCKS,
pac.PLL_SYS, pac.PLL_SYS,
@ -37,14 +69,20 @@ fn main() -> ! {
.ok() .ok()
.unwrap(); .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.IO_BANK0,
pac.PADS_BANK0, pac.PADS_BANK0,
sio.gpio_bank0, sio.gpio_bank0,
&mut pac.RESETS, &mut pac.RESETS,
); );
let mut uart = UartPeripheral::<_, _>::enable( let mut uart = hal::uart::UartPeripheral::<_, _>::enable(
pac.UART0, pac.UART0,
&mut pac.RESETS, &mut pac.RESETS,
hal::uart::common_configs::_9600_8_N_1, hal::uart::common_configs::_9600_8_N_1,
@ -52,16 +90,19 @@ fn main() -> ! {
) )
.unwrap(); .unwrap();
// UART TX (characters sent from pico) on pin 1 (GPIO0) and RX (on pin 2 (GPIO1) // UART TX (characters sent from RP2040) on pin 1 (GPIO0)
let _tx_pin = pins.gpio0.into_mode::<gpio::FunctionUart>(); let _tx_pin = pins.gpio0.into_mode::<hal::gpio::FunctionUart>();
let _rx_pin = pins.gpio1.into_mode::<gpio::FunctionUart>(); // UART RX (characters reveived by RP2040) on pin 2 (GPIO1)
let _rx_pin = pins.gpio1.into_mode::<hal::gpio::FunctionUart>();
uart.write_full_blocking(b"UART example\r\n"); uart.write_full_blocking(b"UART example\r\n");
let mut value = 0u32; let mut value = 0u32;
loop { loop {
writeln!(uart, "value: {:02}\r", value).unwrap(); writeln!(uart, "value: {:02}\r", value).unwrap();
cortex_m::asm::delay(10_000_000); delay.delay_ms(1000);
value += 1 value += 1
} }
} }
// End of file

View file

@ -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_std]
#![no_main] #![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 cortex_m_rt::entry;
use embedded_hal::digital::v2::OutputPin;
use embedded_time::duration::units::*; // Ensure we halt the program on panic (if we don't mention this crate it won't
use embedded_time::fixed_point::FixedPoint; // be linked)
use hal::clocks::{init_clocks_and_plls, Clock};
use hal::gpio::Pins;
use hal::pac;
use hal::sio::Sio;
use hal::watchdog::Watchdog;
use panic_halt as _; use panic_halt as _;
// Alias for our HAL crate
use rp2040_hal as hal; 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"] #[link_section = ".boot2"]
#[used] #[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER; pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER;
// External high-speed crystal on the pico board is 12Mhz /// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
// Adjust for your board if this isn't the same /// if your board has a different frequency
const EXTERNAL_XTAL_FREQ_HZ: u32 = 12_000_000; 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] #[entry]
fn main() -> ! { fn main() -> ! {
// Grab our singleton objects
let mut pac = pac::Peripherals::take().unwrap(); let mut pac = pac::Peripherals::take().unwrap();
let cp = pac::CorePeripherals::take().unwrap(); let core = pac::CorePeripherals::take().unwrap();
let mut watchdog = Watchdog::new(pac.WATCHDOG);
let sio = Sio::new(pac.SIO);
let clocks = init_clocks_and_plls( // Set up the watchdog driver - needed by the clock setup code
EXTERNAL_XTAL_FREQ_HZ, 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.XOSC,
pac.CLOCKS, pac.CLOCKS,
pac.PLL_SYS, pac.PLL_SYS,
@ -42,16 +70,19 @@ fn main() -> ! {
.ok() .ok()
.unwrap(); .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.IO_BANK0,
pac.PADS_BANK0, pac.PADS_BANK0,
sio.gpio_bank0, sio.gpio_bank0,
&mut pac.RESETS, &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 // Configure an LED so we can show the current state of the watchdog
let mut led_pin = pins.gpio25.into_push_pull_output(); let mut led_pin = pins.gpio25.into_push_pull_output();
@ -60,7 +91,7 @@ fn main() -> ! {
delay.delay_ms(2000); delay.delay_ms(2000);
// Set to watchdog to reset if it's not reloaded within 1.05 seconds, and start it // 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 // Blink once a second for 5 seconds, refreshing the watchdog timer once a second to avoid a reset
for _ in 1..=5 { for _ in 1..=5 {
@ -80,3 +111,5 @@ fn main() -> ! {
delay.delay_ms(100); delay.delay_ms(100);
} }
} }
// End of file