From 45580ec4c8c9955ba7cdc403ce3ba30ae6774e9f Mon Sep 17 00:00:00 2001 From: Jennifer Wilcox Date: Sat, 17 Apr 2021 18:18:10 -0500 Subject: [PATCH] Add basic output support for GPIOs --- .gitignore | 1 + Cargo.lock | 117 +++++++++++++++++++++++++++++++++ rp2040-hal/Cargo.toml | 2 +- rp2040-hal/src/gpio.rs | 132 ++++++++++++++++++++++++++++++++++++++ rp2040-hal/src/lib.rs | 1 + rp2040-hal/src/prelude.rs | 1 + 6 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 Cargo.lock create mode 100644 rp2040-hal/src/gpio.rs diff --git a/.gitignore b/.gitignore index 9f11b75..2f5a8f4 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .idea/ +target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c4cfdca --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,117 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "cortex-m" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643a210c1bdc23d0db511e2a576082f4ff4dcae9d0c37f50b431b8f8439d6d6b" +dependencies = [ + "bare-metal", + "bitfield", + "embedded-hal", + "volatile-register", +] + +[[package]] +name = "embedded-hal" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa998ce59ec9765d15216393af37a58961ddcefb14c753b4816ba2191d865fcb" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.0.0", +] + +[[package]] +name = "nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" + +[[package]] +name = "rp2040-hal" +version = "0.1.0" +dependencies = [ + "cortex-m", + "embedded-hal", + "nb 1.0.0", + "rp2040-pac", +] + +[[package]] +name = "rp2040-pac" +version = "0.1.1" +source = "git+https://github.com/rp-rs/rp2040-pac?branch=main#f4339cb856f082970767099a0079259f333cdc7e" +dependencies = [ + "cortex-m", + "vcell", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286" +dependencies = [ + "vcell", +] diff --git a/rp2040-hal/Cargo.toml b/rp2040-hal/Cargo.toml index 782adb1..3d4600a 100644 --- a/rp2040-hal/Cargo.toml +++ b/rp2040-hal/Cargo.toml @@ -13,4 +13,4 @@ license = "MIT OR Apache-2.0" cortex-m = "0.7.1" embedded-hal = "0.2.4" nb = "1.0.0" -rp2040-pac = "0.1.1" +rp2040-pac = { git = "https://github.com/rp-rs/rp2040-pac", branch="main" } diff --git a/rp2040-hal/src/gpio.rs b/rp2040-hal/src/gpio.rs new file mode 100644 index 0000000..53af7e9 --- /dev/null +++ b/rp2040-hal/src/gpio.rs @@ -0,0 +1,132 @@ +//! General Purpose Input and Output (GPIO) +//! +//! TODO: Docs for this whole module +//! +//! For example, to turn on the LED on a Pico board: +//! +//! ```rust +//! let mut pac = rp2040_pac::Peripherals::take().unwrap(); +//! +//! let pins = pac.IO_BANK0.split(&mut pac.RESETS); +//! let mut led_pin = pins.gpio25.into_output(&mut pac.PADS_BANK0, &mut pac.SIO); +//! led_pin.set_low().unwrap(); +//! ``` +use core::convert::Infallible; +use core::marker::PhantomData; +use embedded_hal::digital::v2::OutputPin; + +pub struct Floating; +pub struct Input { + _mode: PhantomData, +} +pub struct Output; + +pub trait GpioExt { + type Parts; + + // TODO: Do we need a marker to check that clocks are up? + fn split(self, reset: &mut rp2040_pac::RESETS) -> Self::Parts; +} + +const FUNCTION_SIO: u8 = 5; + +macro_rules! gpio { + ($GPIOX:ident, $gpiox:ident, $PADSX:ident, [ + $($PXi:ident: ($pxi:ident, $i:expr),)+ + ]) => { + impl GpioExt for pac::$GPIOX { + type Parts = Parts; + + fn split(self, resets: &mut pac::RESETS) -> Parts { + resets.reset.modify(|_, w| w.$gpiox().clear_bit()); + Parts { + $( + $pxi: $PXi { _mode: PhantomData }, + )+ + } + } + } + + pub struct Parts { + $( + pub $pxi: $PXi>, + )+ + } + + $( + pub struct $PXi { + _mode: PhantomData, + } + + impl $PXi { + pub fn into_output( + self, + pads: &mut pac::$PADSX, + sio: &mut pac::SIO, + ) -> $PXi { + pads.gpio[$i].modify(|_, w| w.ie().set_bit().od().clear_bit()); + unsafe { + (*pac::$GPIOX::ptr()).gpio[$i] + .gpio_ctrl + .write_with_zero(|x| x.funcsel().bits(FUNCTION_SIO)); + } + sio.gpio_oe.modify(|_, x| unsafe { x.bits(1 << $i) }); + $PXi { _mode: PhantomData } + } + } + + impl OutputPin for $PXi { + type Error = Infallible; + + fn set_low(&mut self) -> Result<(), Self::Error> { + unsafe { + (*pac::SIO::ptr()).gpio_out_clr.write(|x| x.bits(1 << $i)); + } + Ok(()) + } + + fn set_high(&mut self) -> Result<(), Self::Error> { + unsafe { + (*pac::SIO::ptr()).gpio_out_set.write(|x| x.bits(1 << $i)); + } + Ok(()) + } + } + )+ + }; +} + +gpio!( + IO_BANK0, io_bank0, PADS_BANK0, [ + Gpio0: (gpio0, 0), + Gpio1: (gpio1, 1), + Gpio2: (gpio2, 2), + Gpio3: (gpio3, 3), + Gpio4: (gpio4, 4), + Gpio5: (gpio5, 5), + Gpio6: (gpio6, 6), + Gpio7: (gpio7, 7), + Gpio8: (gpio8, 8), + Gpio9: (gpio9, 9), + Gpio10: (gpio10, 10), + Gpio11: (gpio11, 11), + Gpio12: (gpio12, 12), + Gpio13: (gpio13, 13), + Gpio14: (gpio14, 14), + Gpio15: (gpio15, 15), + Gpio16: (gpio16, 16), + Gpio17: (gpio17, 17), + Gpio18: (gpio18, 18), + Gpio19: (gpio19, 19), + Gpio20: (gpio20, 20), + Gpio21: (gpio21, 21), + Gpio22: (gpio22, 22), + Gpio23: (gpio23, 23), + Gpio24: (gpio24, 24), + Gpio25: (gpio25, 25), + Gpio26: (gpio26, 26), + Gpio27: (gpio27, 27), + Gpio28: (gpio28, 28), + Gpio29: (gpio29, 29), + ] +); diff --git a/rp2040-hal/src/lib.rs b/rp2040-hal/src/lib.rs index e8d96e2..719afcc 100644 --- a/rp2040-hal/src/lib.rs +++ b/rp2040-hal/src/lib.rs @@ -13,6 +13,7 @@ extern crate nb; pub extern crate rp2040_pac as pac; pub mod adc; +pub mod gpio; pub mod i2c; pub mod prelude; pub mod pwm; diff --git a/rp2040-hal/src/prelude.rs b/rp2040-hal/src/prelude.rs index 8e3e645..57edf4f 100644 --- a/rp2040-hal/src/prelude.rs +++ b/rp2040-hal/src/prelude.rs @@ -1 +1,2 @@ //! Prelude +pub use crate::gpio::GpioExt;