Add initial ADC/GPIO implementation for ESP32-H2 (#494)

* Add `esp32h2-hal` package to the VS Code workspace and CI workflow

* Add initial (not quite complete) implementation of GPIO/ADC for ESP32-H2
This commit is contained in:
Jesse Braham 2023-04-27 05:10:38 -07:00 committed by Jesse Braham
parent 854e52c417
commit c3b4e83846
11 changed files with 395 additions and 37 deletions

View File

@ -44,6 +44,8 @@ jobs:
run: cd esp-hal-smartled/ && cargo +nightly-2023-03-09 check --features=esp32c3
- name: check (esp32c6)
run: cd esp-hal-smartled/ && cargo +nightly-2023-03-09 check --features=esp32c6
# - name: check (esp32h2)
# run: cd esp-hal-smartled/ && cargo +nightly-2023-03-09 check --features=esp32h2
# Check all Xtensa targets:
- name: check (esp32)
run: cd esp-hal-smartled/ && cargo +esp check --features=esp32,esp32_40mhz
@ -188,6 +190,39 @@ jobs:
- name: check esp32c6-hal (async, serial)
run: cd esp32c6-hal/ && cargo +nightly-2023-03-09 check --example=embassy_serial --features=embassy,embassy-time-systick,async
esp32h2-hal:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imac-unknown-none-elf
toolchain: nightly-2023-03-09
components: rust-src
- uses: Swatinem/rust-cache@v2
# Perform a full build initially to verify that the examples not only
# build, but also link successfully.
# We also use this as an opportunity to verify that the examples link
# for each supported image format.
- name: build esp32h2-hal (no features)
run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 build --examples
# - name: build esp32h2-hal (direct-boot)
# run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 build --examples --features=direct-boot
# Subsequent steps can just check the examples instead, as we're already
# confident that they link.
- name: check esp32h2-hal (common features)
run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 check --examples --features=eh1,ufmt
# - name: check esp32h2-hal (async, systick)
# run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 check --example=embassy_hello_world --features=embassy,embassy-time-systick
# - name: check esp32h2-hal (async, timg0)
# run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 check --example=embassy_hello_world --features=embassy,embassy-time-timg0
# - name: check esp32h2-hal (async, gpio)
# run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 check --example=embassy_wait --features=embassy,embassy-time-systick,async
# - name: check esp32h2-hal (async, spi)
# run: cd esp32h2-hal/ && cargo +nightly-2023-03-09 check --example=embassy_spi --features=embassy,embassy-time-systick,async
esp32s2-hal:
runs-on: ubuntu-latest
@ -276,6 +311,8 @@ jobs:
run: cd esp32c3-hal/ && cargo check --features=eh1,ufmt
- name: msrv (esp32c6-hal)
run: cd esp32c6-hal/ && cargo check --features=eh1,ufmt
- name: msrv (esp32h2-hal)
run: cd esp32h2-hal/ && cargo check --features=eh1,ufmt
msrv-xtensa:
runs-on: ubuntu-latest
@ -317,6 +354,8 @@ jobs:
run: cargo +stable clippy --manifest-path=esp32c3-hal/Cargo.toml -- --no-deps
- name: clippy (esp32c6-hal)
run: cargo +stable clippy --manifest-path=esp32c6-hal/Cargo.toml -- --no-deps
- name: clippy (esp32h2-hal)
run: cargo +stable clippy --manifest-path=esp32h2-hal/Cargo.toml -- --no-deps
clippy-xtensa:
runs-on: ubuntu-latest
@ -369,6 +408,8 @@ jobs:
run: cargo fmt --all --manifest-path=esp32c3-hal/Cargo.toml -- --check
- name: rustfmt (esp32c6-hal)
run: cargo fmt --all --manifest-path=esp32c6-hal/Cargo.toml -- --check
- name: rustfmt (esp32h2-hal)
run: cargo fmt --all --manifest-path=esp32h2-hal/Cargo.toml -- --check
- name: rustfmt (esp32s2-hal)
run: cargo fmt --all --manifest-path=esp32s2-hal/Cargo.toml -- --check
- name: rustfmt (esp32s3-hal)

View File

@ -5,13 +5,13 @@ cores = "single_core"
peripherals = [
# Peripherals available in the PAC:
# "aes",
# "apb_saradc",
"apb_saradc",
# "assist_debug",
# "ds",
# "ecc",
"efuse",
# "gdma",
# "gpio",
"gpio",
# "hmac",
# "hp_apm",
# "hp_sys",
@ -20,7 +20,7 @@ peripherals = [
# "i2s0",
"interrupt_core0",
"intpri",
# "io_mux",
"io_mux",
# "ledc",
# "lp_ana",
# "lp_aon",
@ -39,7 +39,6 @@ peripherals = [
# "pcnt",
"pcr",
# "pmu",
# "peripherals",
# "rmt",
# "rng",
# "rsa",
@ -48,7 +47,7 @@ peripherals = [
# "spi0",
# "spi1",
# "spi2",
# "systimer",
"systimer",
# "tee",
# "timg0",
# "timg1",
@ -59,7 +58,7 @@ peripherals = [
# "uhci0",
# "usb_device",
# Additional peripherals defined by us (the developers):
"adc",
"plic",
]

View File

@ -367,3 +367,27 @@ pub mod implementation {
]
}
}
#[cfg(esp32h2)]
pub mod implementation {
//! Analog to digital (ADC) conversion support.
//!
//! This module provides functions for reading analog values from one
//! analog to digital converter available on the ESP32-H2: `ADC1`.
use embedded_hal::adc::Channel;
use super::impl_adc_interface;
pub use crate::analog::{adc::*, ADC1};
use crate::gpio::*;
impl_adc_interface! {
ADC1 [
(Gpio1, 0),
(Gpio2, 1),
(Gpio3, 2),
(Gpio4, 3),
(Gpio5, 4),
]
}
}

View File

@ -1,5 +1,5 @@
#[cfg_attr(esp32, path = "adc/esp32.rs")]
#[cfg_attr(any(esp32c2, esp32c3, esp32c6), path = "adc/riscv.rs")]
#[cfg_attr(riscv, path = "adc/riscv.rs")]
#[cfg_attr(any(esp32s2, esp32s3), path = "adc/xtensa.rs")]
pub mod adc;
#[cfg(dac)]
@ -77,7 +77,7 @@ impl crate::peripheral::Peripheral for DAC2 {
impl crate::peripheral::sealed::Sealed for DAC2 {}
cfg_if::cfg_if! {
if #[cfg(any(esp32, esp32s2, esp32s3))] {
if #[cfg(xtensa)] {
use crate::peripherals::SENS;
pub struct AvailableAnalog {
@ -114,7 +114,7 @@ cfg_if::cfg_if! {
}
cfg_if::cfg_if! {
if #[cfg(any(esp32c2, esp32c3, esp32c6))] {
if #[cfg(riscv)] {
use crate::peripherals::APB_SARADC;
pub struct AvailableAnalog {

View File

@ -262,7 +262,7 @@ impl InteruptStatusRegisterAccess for SingleCoreInteruptStatusRegisterAccessBank
// interrupt enable bit see
// https://github.com/espressif/esp-idf/blob/c04803e88b871a4044da152dfb3699cf47354d18/components/hal/esp32s3/include/hal/gpio_ll.h#L32
// Treating it as SingleCore in the gpio macro makes this work.
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32s2, esp32s3)))]
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3)))]
impl InteruptStatusRegisterAccess for DualCoreInteruptStatusRegisterAccessBank0 {
fn pro_cpu_interrupt_status_read() -> u32 {
unsafe { &*GPIO::PTR }.pcpu_int.read().bits()
@ -285,7 +285,7 @@ impl InteruptStatusRegisterAccess for DualCoreInteruptStatusRegisterAccessBank0
// interrupt enable bit see
// https://github.com/espressif/esp-idf/blob/c04803e88b871a4044da152dfb3699cf47354d18/components/hal/esp32s3/include/hal/gpio_ll.h#L32
// Treating it as SingleCore in the gpio macro makes this work.
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32s2, esp32s3)))]
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3)))]
impl InteruptStatusRegisterAccess for DualCoreInteruptStatusRegisterAccessBank1 {
fn pro_cpu_interrupt_status_read() -> u32 {
unsafe { &*GPIO::PTR }.pcpu_int1.read().bits()
@ -449,7 +449,7 @@ impl BankGpioRegisterAccess for Bank0GpioRegisterAccess {
}
}
#[cfg(not(any(esp32c2, esp32c3, esp32c6)))]
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))]
impl BankGpioRegisterAccess for Bank1GpioRegisterAccess {
fn write_out_en_clear(word: u32) {
unsafe { &*GPIO::PTR }
@ -1677,7 +1677,7 @@ pub fn enable_iomux_clk_gate() {
}
}
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32s2)))]
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s2)))]
#[doc(hidden)]
#[macro_export]
macro_rules! analog {
@ -1795,7 +1795,7 @@ macro_rules! analog {
}
}
#[cfg(any(esp32c2, esp32c3, esp32c6))]
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2))]
#[doc(hidden)]
#[macro_export]
macro_rules! analog {

View File

@ -1,31 +1,263 @@
use paste::paste;
use crate::{
gpio::{
AlternateFunction,
Bank0GpioRegisterAccess,
GpioPin,
InputOutputAnalogPinType,
InputOutputPinType,
Unknown,
},
peripherals::GPIO,
};
// https://github.com/espressif/esp-idf/blob/df9310a/components/soc/esp32h2/gpio_periph.c#L42
pub const NUM_PINS: usize = 27;
pub type OutputSignalType = u8;
pub const OUTPUT_SIGNAL_MAX: u8 = 0; // FIXME
pub const INPUT_SIGNAL_MAX: u8 = 0; // FIXME
pub const OUTPUT_SIGNAL_MAX: u8 = 128;
pub const INPUT_SIGNAL_MAX: u8 = 124;
pub const ONE_INPUT: u8 = 0x1e;
pub const ZERO_INPUT: u8 = 0x1f;
/// Peripheral input signals for the GPIO mux
#[allow(non_camel_case_types)]
#[derive(PartialEq, Copy, Clone)]
pub enum InputSignal {}
pub(crate) const GPIO_FUNCTION: AlternateFunction = AlternateFunction::Function1;
pub(crate) const fn get_io_mux_reg(gpio_num: u8) -> &'static crate::peripherals::io_mux::GPIO {
unsafe { &(&*crate::peripherals::IO_MUX::PTR).gpio[gpio_num as usize] }
}
pub(crate) fn gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8 {
int_enable as u8 | ((nmi_enable as u8) << 1)
}
/// Peripheral input signals for the GPIO mux
#[allow(non_camel_case_types)]
#[derive(PartialEq, Copy, Clone)]
pub enum OutputSignal {}
pub enum InputSignal {
EXT_ADC_START = 0,
U0RXD = 6,
U0CTS = 7,
U0DSR = 8,
U1RXD = 9,
U1CTS = 10,
U1DSR = 11,
I2S_MCLK = 12,
I2SO_BCK = 13,
I2SO_WS = 14,
I2SI_SD = 15,
I2SI_BCK = 16,
I2SI_WS = 17,
USB_JTAG_TDO_BRIDGE = 19,
CPU_GPIO0 = 28,
CPU_GPIO1 = 29,
CPU_GPIO2 = 30,
CPU_GPIO3 = 31,
CPU_GPIO4 = 32,
CPU_GPIO5 = 33,
CPU_GPIO6 = 34,
CPU_GPIO7 = 35,
I2CEXT0_SCL = 45,
I2CEXT0_SDA = 46,
PARL_RX_DATA0 = 47,
PARL_RX_DATA1 = 48,
PARL_RX_DATA2 = 49,
PARL_RX_DATA3 = 50,
PARL_RX_DATA4 = 51,
PARL_RX_DATA5 = 52,
PARL_RX_DATA6 = 53,
PARL_RX_DATA7 = 54,
I2CEXT1_SCL = 55,
I2CEXT1_SDA = 56,
FSPICLK = 63,
FSPIQ = 64,
FSPID = 65,
FSPIHD = 66,
FSPIWP = 67,
FSPICS0 = 68,
PARL_RX_CLK = 69,
PARL_TX_CLK = 70,
RMT_SIG0 = 71,
RMT_SIG1 = 72,
TWAI0_RX = 73,
PWM0_SYNC0 = 87,
PWM0_SYNC1 = 88,
PWM0_SYNC2 = 89,
PWM0_F0 = 90,
PWM0_F1 = 91,
PWM0_F2 = 92,
PWM0_CAP0 = 93,
PWM0_CAP1 = 94,
PWM0_CAP2 = 95,
SIG_FUNC_97 = 97,
SIG_FUNC_98 = 98,
SIG_FUNC_99 = 99,
SIG_FUNC_100 = 100,
PCNT_SIG_CH00 = 101,
PCNT_SIG_CH10 = 102,
PCNT_CTRL_CH00 = 103,
PCNT_CTRL_CH10 = 104,
PCNT_SIG_CH01 = 105,
PCNT_SIG_CH11 = 106,
PCNT_CTRL_CH01 = 107,
PCNT_CTRL_CH11 = 108,
PCNT_SIG_CH02 = 109,
PCNT_SIG_CH12 = 110,
PCNT_CTRL_CH02 = 111,
PCNT_CTRL_CH12 = 112,
PCNT_SIG_CH03 = 113,
PCNT_SIG_CH13 = 114,
PCNT_CTRL_CH03 = 115,
PCNT_CTRL_CH13 = 116,
SPIQ = 121,
SPID = 122,
SPIHD = 123,
SPIWP = 124,
}
// crate::gpio::gpio! {}
/// Peripheral input signals for the GPIO mux
#[allow(non_camel_case_types)]
#[derive(PartialEq, Copy, Clone)]
pub enum OutputSignal {
LEDC_LS_SIG_OUT0 = 0,
LEDC_LS_SIG_OUT1 = 1,
LEDC_LS_SIG_OUT2 = 2,
LEDC_LS_SIG_OUT3 = 3,
LEDC_LS_SIG_OUT4 = 4,
LEDC_LS_SIG_OUT5 = 5,
U0TXD = 6,
U0RTS = 7,
U0DTR = 8,
U1TXD = 9,
U1RTS = 10,
U1DTR = 11,
I2S_MCLK = 12,
I2SO_BCK = 13,
I2SO_WS = 14,
I2SO_SD = 15,
I2SI_BCK = 16,
I2SI_WS = 17,
I2SO_SD1 = 18,
USB_JTAG_TRST = 19,
CPU_GPIO_OUT0 = 28,
CPU_GPIO_OUT1 = 29,
CPU_GPIO_OUT2 = 30,
CPU_GPIO_OUT3 = 31,
CPU_GPIO_OUT4 = 32,
CPU_GPIO_OUT5 = 33,
CPU_GPIO_OUT6 = 34,
CPU_GPIO_OUT7 = 35,
I2CEXT0_SCL = 45,
I2CEXT0_SDA = 46,
PARL_TX_DATA0 = 47,
PARL_TX_DATA1 = 48,
PARL_TX_DATA2 = 49,
PARL_TX_DATA3 = 50,
PARL_TX_DATA4 = 51,
PARL_TX_DATA5 = 52,
PARL_TX_DATA6 = 53,
PARL_TX_DATA7 = 54,
I2CEXT1_SCL = 55,
I2CEXT1_SDA = 56,
FSPICLK_OUT_MUX = 63,
FSPIQ = 64,
FSPID = 65,
FSPIHD = 66,
FSPIWP = 67,
FSPICS0 = 68,
PARL_RX_CLK = 69,
PARL_TX_CLK = 70,
RMT_SIG_OUT0 = 71,
RMT_SIG_OUT1 = 72,
TWAI0_TX = 73,
TWAI0_BUS_OFF_ON = 74,
TWAI0_CLKOUT = 75,
TWAI0_STANDBY = 76,
CTE_ANT7 = 78,
CTE_ANT8 = 79,
CTE_ANT9 = 80,
GPIO_SD0 = 83,
GPIO_SD1 = 84,
GPIO_SD2 = 85,
GPIO_SD3 = 86,
PWM0_OUT0A = 87,
PWM0_OUT0B = 88,
PWM0_OUT1A = 89,
PWM0_OUT1B = 90,
PWM0_OUT2A = 91,
PWM0_OUT2B = 92,
SIG_IN_FUNC97 = 97,
SIG_IN_FUNC98 = 98,
SIG_IN_FUNC99 = 99,
SIG_IN_FUNC100 = 100,
FSPICS1 = 101,
FSPICS2 = 102,
FSPICS3 = 103,
FSPICS4 = 104,
FSPICS5 = 105,
CTE_ANT10 = 106,
CTE_ANT11 = 107,
CTE_ANT12 = 108,
CTE_ANT13 = 109,
CTE_ANT14 = 110,
CTE_ANT15 = 111,
SPICLK_OUT_MUX = 114,
SPICS0 = 115,
SPICS1 = 116,
SPIQ = 121,
SPID = 122,
SPIHD = 123,
SPIWP = 124,
CLK_OUT_OUT1 = 125,
CLK_OUT_OUT2 = 126,
CLK_OUT_OUT3 = 127,
GPIO = 128,
}
// crate::gpio::analog! {}
// FIXME: add alternate function numbers/signals where necessary
crate::gpio::gpio! {
Single,
(0, 0, InputOutput)
(1, 0, InputOutputAnalog)
(2, 0, InputOutputAnalog)
(3, 0, InputOutputAnalog)
(4, 0, InputOutputAnalog)
(5, 0, InputOutputAnalog)
(6, 0, InputOutput)
(7, 0, InputOutput)
(8, 0, InputOutput)
(9, 0, InputOutput)
(10, 0, InputOutput)
(11, 0, InputOutput)
(12, 0, InputOutput)
(13, 0, InputOutput)
(14, 0, InputOutput)
(15, 0, InputOutput)
(16, 0, InputOutput)
(17, 0, InputOutput)
(18, 0, InputOutput)
(19, 0, InputOutput)
(20, 0, InputOutput)
(21, 0, InputOutput)
(22, 0, InputOutput)
(23, 0, InputOutput)
(24, 0, InputOutput)
(25, 0, InputOutput)
(26, 0, InputOutput)
(27, 0, InputOutput)
}
crate::gpio::analog! {
1
2
3
4
5
}
// TODO USB pins
// implement marker traits on USB pins
// impl<T> crate::otg_fs::UsbSel for Gpio??<T> {}
// impl<T> crate::otg_fs::UsbDp for Gpio12<T> {}
// impl<T> crate::otg_fs::UsbDm for Gpio13<T> {}
// impl<T> crate::otg_fs::UsbDp for Gpio27<T> {}
// impl<T> crate::otg_fs::UsbDm for Gpio26<T> {}

View File

@ -7,13 +7,13 @@ pub(crate) use self::peripherals::*;
crate::peripherals! {
// AES => true,
// APB_SARADC => true,
APB_SARADC => true,
// ASSIST_DEBUG => true,
// DS => true,
// ECC => true,
EFUSE => true,
// GDMA => true,
// GPIO => true,
GPIO => true,
// HMAC => true,
// HP_APM => true,
// HP_SYS => true,
@ -22,7 +22,7 @@ crate::peripherals! {
// I2S0 => true,
INTERRUPT_CORE0 => true,
INTPRI => true,
// IO_MUX => true,
IO_MUX => true,
// LEDC => true,
// LP_ANA => true,
// LP_AON => true,
@ -41,7 +41,6 @@ crate::peripherals! {
// PCNT => true,
PCR => true,
// PMU => true,
// Peripherals => true,
// RMT => true,
// RNG => true,
// RSA => true,
@ -50,7 +49,7 @@ crate::peripherals! {
// SPI0 => true,
// SPI1 => true,
// SPI2 => true,
// SYSTIMER => true,
SYSTIMER => true,
// TEE => true,
// TIMG0 => true,
// TIMG1 => true,

View File

@ -21,6 +21,9 @@
{
"path": "esp32c6-hal"
},
{
"path": "esp32h2-hal"
},
{
"path": "esp32s2-hal"
},

View File

@ -2,7 +2,8 @@
name = "esp32h2-hal"
version = "0.1.0"
authors = [
"Kirill Mikhailov <playfulfence@gmail.com>"
"Kirill Mikhailov <playfulfence@gmail.com>",
"Jesse Braham <jesse@beta7.io>",
]
edition = "2021"
rust-version = "1.60.0"
@ -57,4 +58,3 @@ async = ["esp-hal-common/async", "embedded-hal-async"]
embassy = ["esp-hal-common/embassy"]
embassy-time-systick = ["esp-hal-common/embassy-time-systick", "embassy-time/tick-hz-16_000_000"]
embassy-time-timg0 = ["esp-hal-common/embassy-time-timg0", "embassy-time/tick-hz-1_000_000"]

View File

@ -0,0 +1,60 @@
//! Blinks an LED
//!
//! This assumes that a LED is connected to the pin assigned to `led`. (GPIO5)
#![no_std]
#![no_main]
use esp32h2_hal::{
clock::ClockControl,
gpio::IO,
peripherals::Peripherals,
prelude::*,
// timer::TimerGroup,
Delay,
// Rtc,
};
use esp_backtrace as _;
#[entry]
fn main() -> ! {
let peripherals = Peripherals::take();
let mut system = peripherals.PCR.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
// Disable the watchdog timers. For the ESP32-H2, this includes the Super WDT,
// and the TIMG WDTs.
// let mut rtc = Rtc::new(peripherals.LP_CLKRST);
// let timer_group0 = TimerGroup::new(
// peripherals.TIMG0,
// &clocks,
// &mut system.peripheral_clock_control,
// );
// let mut wdt0 = timer_group0.wdt;
// let timer_group1 = TimerGroup::new(
// peripherals.TIMG1,
// &clocks,
// &mut system.peripheral_clock_control,
// );
// let mut wdt1 = timer_group1.wdt;
// rtc.swd.disable();
// rtc.rwdt.disable();
// wdt0.disable();
// wdt1.disable();
// Set GPIO5 as an output, and set its state high initially.
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let mut led = io.pins.gpio5.into_push_pull_output();
led.set_high().unwrap();
// Initialize the Delay peripheral, and use it to toggle the LED state in a
// loop.
let mut delay = Delay::new(&clocks);
loop {
led.toggle().unwrap();
delay.delay_ms(500u32);
}
}

View File

@ -6,9 +6,9 @@ pub use embedded_hal as ehal;
pub use esp_hal_common::embassy;
pub use esp_hal_common::*;
// pub use self::gpio::IO;
pub use self::gpio::IO;
// /// Common module for analog functions
// pub mod analog {
// pub use esp_hal_common::analog::{AvailableAnalog, SarAdcExt};
// }
/// Common module for analog functions
pub mod analog {
pub use esp_hal_common::analog::{AvailableAnalog, SarAdcExt};
}