From b5a38f80f2701f48a6468db55a372eba1a74e1eb Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Fri, 11 Aug 2023 12:57:35 +0200 Subject: [PATCH 1/2] ESP32-C6 LP CORE delay and basic gpio --- esp32c6-lp-hal/.cargo/config.toml | 2 +- esp32c6-lp-hal/Cargo.toml | 5 ++ esp32c6-lp-hal/examples/blinky.rs | 34 +++++++++++++ esp32c6-lp-hal/src/delay.rs | 41 ++++++++++++++++ esp32c6-lp-hal/src/gpio.rs | 80 +++++++++++++++++++++++++++++++ esp32c6-lp-hal/src/lib.rs | 6 +++ esp32c6-lp-hal/src/prelude.rs | 9 ++++ 7 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 esp32c6-lp-hal/examples/blinky.rs create mode 100644 esp32c6-lp-hal/src/delay.rs create mode 100644 esp32c6-lp-hal/src/gpio.rs create mode 100644 esp32c6-lp-hal/src/prelude.rs diff --git a/esp32c6-lp-hal/.cargo/config.toml b/esp32c6-lp-hal/.cargo/config.toml index b546dc33976..67f78b7ee67 100644 --- a/esp32c6-lp-hal/.cargo/config.toml +++ b/esp32c6-lp-hal/.cargo/config.toml @@ -1,7 +1,7 @@ [target.riscv32imac-unknown-none-elf] runner = "espflash flash --monitor" rustflags = [ - "-C", "link-arg=-Tlinkall.x", + "-C", "link-arg=-Tlink.x", ] [build] diff --git a/esp32c6-lp-hal/Cargo.toml b/esp32c6-lp-hal/Cargo.toml index bc58105f2ee..c2c2beb4d4d 100644 --- a/esp32c6-lp-hal/Cargo.toml +++ b/esp32c6-lp-hal/Cargo.toml @@ -25,6 +25,11 @@ critical-section = { version = "1.1.2", features = ["restore-state-u8"] } embedded-hal = { version = "0.2.7", features = ["unproven"] } esp32c6-lp = { git = "https://github.com/esp-rs/esp-pacs", rev = "a9cad5e", features = ["critical-section"] } riscv = "0.10.1" +riscv-rt-macros = "0.2.0" +paste = "1.0.14" + +[dev-dependencies] +panic-halt = "0.2.0" [features] default = [] diff --git a/esp32c6-lp-hal/examples/blinky.rs b/esp32c6-lp-hal/examples/blinky.rs new file mode 100644 index 00000000000..628a6067b09 --- /dev/null +++ b/esp32c6-lp-hal/examples/blinky.rs @@ -0,0 +1,34 @@ +//! Counts a 32 bit value at 0x5000_2000 and blinks GPIO 1. +//! Make sure the LP RAM is cleared before loading the code. + +#![no_std] +#![no_main] + +use esp32c6_lp_hal::{gpio::Io, prelude::*}; +use panic_halt as _; + +#[entry] +fn main() -> ! { + let mut i: u32 = 0; + + let peripherals = esp32c6_lp::Peripherals::take().unwrap(); + + let io = Io::new(peripherals.LP_IO); + let mut gpio1 = io.gpio1.into_output(); + + let ptr = 0x5000_2000 as *mut u32; + let mut delay = delay::Delay::new(); + + loop { + i = i.wrapping_add(1u32); + unsafe { + ptr.write_volatile(i); + } + + gpio1.set_high().unwrap(); + delay.delay_ms(500); + + gpio1.set_low().unwrap(); + delay.delay_ms(500); + } +} diff --git a/esp32c6-lp-hal/src/delay.rs b/esp32c6-lp-hal/src/delay.rs new file mode 100644 index 00000000000..a973390dac1 --- /dev/null +++ b/esp32c6-lp-hal/src/delay.rs @@ -0,0 +1,41 @@ +//! Simple blocking delay functionality +//! +//! This uses the delay functionality provided by the `riscv` crate under the +//! hood. + +use embedded_hal::blocking::delay::{DelayMs, DelayUs}; + +use crate::CPU_CLOCK; + +pub struct Delay { + rv_delay: riscv::delay::McycleDelay, +} + +impl Delay { + pub fn new() -> Self { + Self { + rv_delay: riscv::delay::McycleDelay::new(CPU_CLOCK), + } + } +} + +impl DelayUs for Delay { + #[inline(always)] + fn delay_us(&mut self, us: u64) { + self.rv_delay.delay_us(us); + } +} + +impl DelayUs for Delay { + #[inline(always)] + fn delay_us(&mut self, us: u32) { + self.rv_delay.delay_us(us); + } +} + +impl DelayMs for Delay { + #[inline(always)] + fn delay_ms(&mut self, ms: u32) { + self.rv_delay.delay_ms(ms); + } +} diff --git a/esp32c6-lp-hal/src/gpio.rs b/esp32c6-lp-hal/src/gpio.rs new file mode 100644 index 00000000000..8bc7942085e --- /dev/null +++ b/esp32c6-lp-hal/src/gpio.rs @@ -0,0 +1,80 @@ +//! LP-GPIO driver +//! +//! It's assumed that GPIOs are already configured correctly by the HP core. + +use core::{convert::Infallible, marker::PhantomData}; + +use embedded_hal::digital::v2::OutputPin; + +pub struct Unknown {} + +pub struct Output; + +#[non_exhaustive] +pub struct GpioPin { + phantom: PhantomData, +} + +#[non_exhaustive] +pub struct Io { + _peripheral: esp32c6_lp::LP_IO, + + pub gpio0: GpioPin<0, Unknown>, + pub gpio1: GpioPin<1, Unknown>, + pub gpio2: GpioPin<2, Unknown>, + pub gpio3: GpioPin<3, Unknown>, + pub gpio4: GpioPin<4, Unknown>, + pub gpio5: GpioPin<5, Unknown>, + pub gpio6: GpioPin<6, Unknown>, + pub gpio7: GpioPin<7, Unknown>, +} + +impl Io { + pub fn new(peripheral: esp32c6_lp::LP_IO) -> Self { + Self { + _peripheral: peripheral, + gpio0: GpioPin::new(), + gpio1: GpioPin::new(), + gpio2: GpioPin::new(), + gpio3: GpioPin::new(), + gpio4: GpioPin::new(), + gpio5: GpioPin::new(), + gpio6: GpioPin::new(), + gpio7: GpioPin::new(), + } + } +} + +impl GpioPin { + fn new() -> Self { + GpioPin { + phantom: PhantomData::default(), + } + } + + /// Assuming the GPIO is already configured by the HP core this makes the + /// GPIO into an output pin. + pub fn into_output(self) -> GpioPin { + GpioPin::new() + } +} + +impl OutputPin for GpioPin { + type Error = Infallible; + + fn set_low(&mut self) -> Result<(), Self::Error> { + let lp_gpio = unsafe { &*esp32c6_lp::LP_IO::PTR }; + lp_gpio + .out_w1tc + .write(|w| w.out_data_w1tc().variant(1 << PIN)); + Ok(()) + } + + fn set_high(&mut self) -> Result<(), Self::Error> { + let lp_gpio = unsafe { &*esp32c6_lp::LP_IO::PTR }; + lp_gpio + .out_w1ts + .write(|w| w.out_data_w1ts().variant(1 << PIN)); + Ok(()) + } +} diff --git a/esp32c6-lp-hal/src/lib.rs b/esp32c6-lp-hal/src/lib.rs index 3e93e22e67e..2c116927488 100644 --- a/esp32c6-lp-hal/src/lib.rs +++ b/esp32c6-lp-hal/src/lib.rs @@ -2,6 +2,9 @@ use core::arch::global_asm; +pub mod delay; +pub mod gpio; + pub mod riscv { //! Low level access to RISC-V processors. //! @@ -9,6 +12,9 @@ pub mod riscv { pub use riscv::*; } +pub mod prelude; + +const CPU_CLOCK: u32 = 16_000_000; global_asm!( r#" diff --git a/esp32c6-lp-hal/src/prelude.rs b/esp32c6-lp-hal/src/prelude.rs new file mode 100644 index 00000000000..98a2bf555ba --- /dev/null +++ b/esp32c6-lp-hal/src/prelude.rs @@ -0,0 +1,9 @@ +//! The prelude +//! +//! Re-exports all traits required for interacting with the various peripheral +//! drivers implemented in this crate. + +pub use embedded_hal::{digital::v2::OutputPin, prelude::*}; +pub use riscv_rt_macros::entry; + +pub use crate::delay; From 854e9fded58a7def1b1820f4e973ad6076408861 Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Fri, 11 Aug 2023 13:08:43 +0200 Subject: [PATCH 2/2] CHANGELOG.md, build LP examples in release mode --- .github/workflows/ci.yml | 2 +- CHANGELOG.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d899ede91cb..0cbb6eac9da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -244,7 +244,7 @@ jobs: # Perform a full build initially to verify that the examples not only # build, but also link successfully. - name: build esp32c6-lp-hal (no features) - run: cd esp32c6-lp-hal/ && cargo +nightly build --examples + run: cd esp32c6-lp-hal/ && cargo +nightly build --release --examples # Ensure documentation can be built - name: rustdoc run: cd esp32c6-lp-hal/ && cargo doc diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f78347fdd0..7405197ffd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add the `esp32c6-lp-hal` package (#714) +- Add GPIO (output) and delay functionality to `esp32c6-lp-hal` (#715) ### Changed