[ESP32-C6-LP] Add input support for IO driver, implement more embedded-hal output traits (#720)

* Add input support for IO driver, implement more `embedded-hal` output traits

* Update CHANGELOG
This commit is contained in:
Jesse Braham 2023-08-14 07:45:17 -07:00 committed by GitHub
parent a2ae6f37d1
commit 2dee0110be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 31 deletions

View File

@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add the `esp32c6-lp-hal` package (#714)
- Add GPIO (output) and delay functionality to `esp32c6-lp-hal` (#715)
- Implement RTCIO pullup, pulldown and hold control for Xtensa MCUs (#684)
- Add GPIO input support and implement additional `embedded-hal` output traits for the C6's LP core [#720]
### Changed

View File

@ -4,7 +4,7 @@
#![no_std]
#![no_main]
use esp32c6_lp_hal::{gpio::Io, prelude::*};
use esp32c6_lp_hal::{delay::Delay, gpio::IO, prelude::*};
use panic_halt as _;
#[entry]
@ -13,11 +13,11 @@ fn main() -> ! {
let peripherals = esp32c6_lp::Peripherals::take().unwrap();
let io = Io::new(peripherals.LP_IO);
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();
let mut delay = Delay::new();
loop {
i = i.wrapping_add(1u32);

View File

@ -1,23 +1,14 @@
//! LP-GPIO driver
//! Low-power 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;
use esp32c6_lp::LP_IO;
#[non_exhaustive]
pub struct GpioPin<const PIN: u8, MODE> {
phantom: PhantomData<MODE>,
}
#[non_exhaustive]
pub struct Io {
_peripheral: esp32c6_lp::LP_IO,
pub struct IO {
_peripheral: LP_IO,
pub gpio0: GpioPin<0, Unknown>,
pub gpio1: GpioPin<1, Unknown>,
@ -29,10 +20,11 @@ pub struct Io {
pub gpio7: GpioPin<7, Unknown>,
}
impl Io {
pub fn new(peripheral: esp32c6_lp::LP_IO) -> Self {
impl IO {
pub fn new(peripheral: LP_IO) -> Self {
Self {
_peripheral: peripheral,
gpio0: GpioPin::new(),
gpio1: GpioPin::new(),
gpio2: GpioPin::new(),
@ -45,13 +37,30 @@ impl Io {
}
}
pub struct Unknown {}
pub struct Input;
pub struct Output;
#[non_exhaustive]
pub struct GpioPin<const PIN: u8, MODE> {
phantom: PhantomData<MODE>,
}
impl<const PIN: u8, MODE> GpioPin<PIN, MODE> {
fn new() -> Self {
GpioPin {
phantom: PhantomData::default(),
phantom: PhantomData,
}
}
/// Assuming the GPIO is already configured by the HP core this makes the
/// GPIO into an input pin.
pub fn into_input(self) -> GpioPin<PIN, Input> {
GpioPin::new()
}
/// 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> {
@ -59,22 +68,64 @@ impl<const PIN: u8, MODE> GpioPin<PIN, MODE> {
}
}
impl<const PIN: u8> OutputPin for GpioPin<PIN, Output> {
impl<const PIN: u8> GpioPin<PIN, Input> {
fn input_state(&self) -> bool {
unsafe { &*LP_IO::PTR }.in_.read().bits() >> PIN & 0x1 != 0
}
}
impl<const PIN: u8> GpioPin<PIN, Output> {
fn output_state(&self) -> bool {
unsafe { &*LP_IO::PTR }.out.read().bits() >> PIN & 0x1 != 0
}
fn set_output_low(&mut self) {
unsafe { &*LP_IO::PTR }
.out_w1tc
.write(|w| w.out_data_w1tc().variant(1 << PIN));
}
fn set_output_high(&mut self) {
unsafe { &*LP_IO::PTR }
.out_w1ts
.write(|w| w.out_data_w1ts().variant(1 << PIN));
}
}
impl<const PIN: u8> embedded_hal::digital::v2::InputPin for GpioPin<PIN, Input> {
type Error = Infallible;
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(self.input_state())
}
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(!self.is_high()?)
}
}
impl<const PIN: u8> embedded_hal::digital::v2::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));
self.set_output_low();
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));
self.set_output_high();
Ok(())
}
}
impl<const PIN: u8> embedded_hal::digital::v2::StatefulOutputPin for GpioPin<PIN, Output> {
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(self.output_state())
}
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(!self.is_set_high()?)
}
}
impl<const PIN: u8> embedded_hal::digital::v2::toggleable::Default for GpioPin<PIN, Output> {}

View File

@ -3,7 +3,13 @@
//! 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 embedded_hal::{
digital::v2::{
InputPin as _embedded_hal_digital_vs_InputPin,
OutputPin as _embedded_hal_digital_vs_OutputPin,
StatefulOutputPin as _embedded_hal_digital_vs_StatefulOutputPin,
ToggleableOutputPin as _embedded_hal_digital_vs_ToggleableOutputPin,
},
prelude::*,
};
pub use riscv_rt_macros::entry;
pub use crate::delay;