Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ jobs:
# confident that they link.
- name: check esp32h2-hal (common features)
run: cd esp32h2-hal/ && cargo +nightly check --examples --features=eh1,ufmt
- name: check esp32h2-hal (async, i2c)
run: cd esp32h2-hal/ && cargo check --example=embassy_i2c --features=embassy,embassy-time-systick,async
# - name: check esp32h2-hal (async, systick)
# run: cd esp32h2-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-systick
# - name: check esp32h2-hal (async, timg0)
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add initial support for SHA in ESP32-H2 (#527)
- Add initial support for AES in ESP32-H2 (#528)
- Add blinky_erased_pins example for ESP32-H2 (#530)
- Add initial support for I2C in ESP32-H2 (#538)

### Fixed

Expand Down
4 changes: 2 additions & 2 deletions esp-hal-common/devices/esp32h2.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ peripherals = [
# "hmac",
# "hp_apm",
# "hp_sys",
# "i2c0",
# "i2c1",
"i2c0",
"i2c1",
# "i2s0",
"interrupt_core0",
"intpri",
Expand Down
16 changes: 6 additions & 10 deletions esp-hal-common/src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ enum Ack {
Nack,
}

#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))]
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
enum Opcode {
RStart = 6,
Write = 1,
Expand Down Expand Up @@ -648,11 +648,7 @@ pub trait Instance {
// Configure frequency
self.set_frequency(clocks.i2c_clock.convert(), frequency);

// Propagate configuration changes (only necessary with C2, C3, and S3)
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))]
self.register_block()
.ctr
.modify(|_, w| w.conf_upgate().set_bit());
self.update_config();

// Reset entire peripheral (also resets fifo)
self.reset();
Expand Down Expand Up @@ -850,7 +846,7 @@ pub trait Instance {
);
}

#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))]
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
/// Sets the frequency of the I2C interface by calculating and applying the
/// associated timings - corresponds to i2c_ll_cal_bus_clk and
/// i2c_ll_set_bus_timing in ESP-IDF
Expand Down Expand Up @@ -938,7 +934,7 @@ pub trait Instance {
) {
unsafe {
// divider
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))]
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
self.register_block().clk_conf.modify(|_, w| {
w.sclk_sel()
.clear_bit()
Expand Down Expand Up @@ -1275,8 +1271,8 @@ pub trait Instance {

fn update_config(&self) {
// Ensure that the configuration of the peripheral is correctly propagated
// (only necessary for C3 and S3 variant)
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))]
// (only necessary for C2, C3, C6, H2 and S3 variant)
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
self.register_block()
.ctr
.modify(|_, w| w.conf_upgate().set_bit());
Expand Down
4 changes: 2 additions & 2 deletions esp-hal-common/src/soc/esp32h2/peripherals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ crate::peripherals! {
// HMAC => true,
// HP_APM => true,
// HP_SYS => true,
// I2C0 => true,
// I2C1 => true,
I2C0 => true,
I2C1 => true,
// I2S0 => true,
INTERRUPT_CORE0 => true,
INTPRI => true,
Expand Down
8 changes: 8 additions & 0 deletions esp-hal-common/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,14 @@ impl PeripheralClockControl {
system.i2c0_conf.modify(|_, w| w.i2c0_rst_en().clear_bit());
}
}
#[cfg(i2c1)]
Peripheral::I2cExt1 => {
#[cfg(esp32h2)]
{
system.i2c1_conf.modify(|_, w| w.i2c1_clk_en().set_bit());
system.i2c1_conf.modify(|_, w| w.i2c1_rst_en().clear_bit());
}
}
#[cfg(rmt)]
Peripheral::Rmt => {
system.rmt_conf.modify(|_, w| w.rmt_clk_en().set_bit());
Expand Down
7 changes: 6 additions & 1 deletion esp32h2-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ esp-hal-common = { version = "0.9.0", features = ["esp32h2"], path = "../es
aes = "0.8.2"
critical-section = "1.1.1"
crypto-bigint = { version = "0.5.2", default-features = false }
embassy-executor = { version = "0.2.0", features = ["nightly", "integrated-timers"] }
embassy-executor = { version = "0.2.0", features = ["nightly", "integrated-timers", "arch-riscv32", "executor-thread"] }
embedded-graphics = "0.7.1"
esp-backtrace = { version = "0.7.0", features = ["esp32h2", "panic-handler", "exception-handler", "print-uart"] }
# esp-hal-smartled = { version = "0.1.0", features = ["esp32h2"], path = "../esp-hal-smartled" }
esp-println = { version = "0.5.0", features = ["esp32h2"] }
lis3dh-async = "0.7.0"
sha2 = { version = "0.10.6", default-features = false}
smart-leds = "0.3.0"
ssd1306 = "0.7.1"
Expand All @@ -59,3 +60,7 @@ 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"]

[[example]]
name = "embassy_i2c"
required-features = ["embassy", "async", "embassy-time-systick"]
101 changes: 101 additions & 0 deletions esp32h2-hal/examples/embassy_i2c.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//! Embassy I2C
//!
//! Folowing pins are used:
//! SDA GPIO1
//! SCL GPIO2
//!
//! Depending on your target and the board you are using you have to change the
//! pins.
//!
//! This is an example of running the embassy executor with IC2. It uses an
//! LIS3DH to get accelerometer data.

#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]

use embassy_executor::Executor;
use embassy_time::{Duration, Timer};
use esp32h2_hal::{
clock::ClockControl,
embassy,
i2c::I2C,
peripherals::{Interrupt, Peripherals, I2C0},
prelude::*,
timer::TimerGroup,
Priority,
Rtc,
IO,
};
use esp_backtrace as _;
use lis3dh_async::{Lis3dh, Range, SlaveAddr};
use static_cell::StaticCell;

#[embassy_executor::task]
async fn run(i2c: I2C<'static, I2C0>) {
let mut lis3dh = Lis3dh::new_i2c(i2c, SlaveAddr::Alternate).await.unwrap();
lis3dh.set_range(Range::G8).await.unwrap();

loop {
let norm = lis3dh.accel_norm().await.unwrap();
esp_println::println!("X: {:+.5} Y: {:+.5} Z: {:+.5}", norm.x, norm.y, norm.z);

Timer::after(Duration::from_millis(100)).await;
}
}

static EXECUTOR: StaticCell<Executor> = StaticCell::new();

#[entry]
fn main() -> ! {
let peripherals = Peripherals::take();
let mut system = peripherals.PCR.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();

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;

// Disable watchdog timers
rtc.swd.disable();
rtc.rwdt.disable();
wdt0.disable();
wdt1.disable();

#[cfg(feature = "embassy-time-systick")]
embassy::init(
&clocks,
esp32h2_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
);

#[cfg(feature = "embassy-time-timg0")]
embassy::init(&clocks, timer_group0.timer0);

let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

let i2c0 = I2C::new(
peripherals.I2C0,
io.pins.gpio1,
io.pins.gpio2,
400u32.kHz(),
&mut system.peripheral_clock_control,
&clocks,
);

esp32h2_hal::interrupt::enable(Interrupt::I2C_EXT0, Priority::Priority1).unwrap();

let executor = EXECUTOR.init(Executor::new());
executor.run(|spawner| {
spawner.spawn(run(i2c0)).ok();
});
}
69 changes: 69 additions & 0 deletions esp32h2-hal/examples/i2c_bmp180_calibration_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//! Read calibration data from BMP180 sensor
//!
//! This example dumps the calibration data from a BMP180 sensor
//!
//! The following wiring is assumed:
//! - SDA => GPIO1
//! - SCL => GPIO2

#![no_std]
#![no_main]

use esp32h2_hal::{
clock::ClockControl,
gpio::IO,
i2c::I2C,
peripherals::Peripherals,
prelude::*,
timer::TimerGroup,
Rtc,
};
use esp_backtrace as _;
use esp_println::println;

#[entry]
fn main() -> ! {
let peripherals = Peripherals::take();
let mut system = peripherals.PCR.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();

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;

// Disable watchdog timers
rtc.swd.disable();
rtc.rwdt.disable();
wdt0.disable();
wdt1.disable();

let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);

// Create a new peripheral object with the described wiring
// and standard I2C clock speed
let mut i2c = I2C::new(
peripherals.I2C0,
io.pins.gpio1,
io.pins.gpio2,
100u32.kHz(),
&mut system.peripheral_clock_control,
&clocks,
);

loop {
let mut data = [0u8; 22];
i2c.write_read(0x77, &[0xaa], &mut data).ok();

println!("{:02x?}", data);
}
}
Loading