ESP32-C6 LP CORE delay and basic gpio (#715)

* ESP32-C6 LP CORE delay and basic gpio

* CHANGELOG.md, build LP examples in release mode
This commit is contained in:
Björn Quentin 2023-08-12 16:04:25 +02:00 committed by GitHub
parent 64556da803
commit bbe1e5df59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 178 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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 = []

View File

@ -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);
}
}

View File

@ -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<u64> for Delay {
#[inline(always)]
fn delay_us(&mut self, us: u64) {
self.rv_delay.delay_us(us);
}
}
impl DelayUs<u32> for Delay {
#[inline(always)]
fn delay_us(&mut self, us: u32) {
self.rv_delay.delay_us(us);
}
}
impl DelayMs<u32> for Delay {
#[inline(always)]
fn delay_ms(&mut self, ms: u32) {
self.rv_delay.delay_ms(ms);
}
}

View File

@ -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<const PIN: u8, MODE> {
phantom: PhantomData<MODE>,
}
#[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<const PIN: u8, MODE> GpioPin<PIN, MODE> {
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<PIN, Output> {
GpioPin::new()
}
}
impl<const PIN: u8> OutputPin for GpioPin<PIN, Output> {
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(())
}
}

View File

@ -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#"

View File

@ -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;