esp-rs / esp-hal

no_std Hardware Abstraction Layers for ESP32 microcontrollers
https://docs.esp-rs.org/esp-hal/
Apache License 2.0
744 stars 207 forks source link

esp32s3: i2c async broken in #1900 #1916

Closed liebman closed 2 months ago

liebman commented 2 months ago

Async i2c write_read() hangs after #1900 on an esp32s3

This small program reads the seconds register from a DS3231 on pins sda:40 scl:41 once a second.

#![no_std]
#![no_main]

use embassy_executor::Spawner;
use embassy_time::{Duration, Timer};
use esp_backtrace as _;
use esp_hal::{
    clock::ClockControl,
    gpio::Io,
    i2c::I2C,
    peripherals::Peripherals,
    prelude::*,
    system::SystemControl,
    timer::{timg::TimerGroup, ErasedTimer, OneShotTimer},
};
use esp_println::println;

macro_rules! mk_static {
    ($t:ty,$val:expr) => {{
        static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
        #[deny(unused_attributes)]
        let x = STATIC_CELL.uninit().write(($val));
        x
    }};
}

#[esp_hal_embassy::main]
async fn main(_spawner: Spawner) {
    let peripherals = Peripherals::take();
    let system = SystemControl::new(peripherals.SYSTEM);
    let clocks = ClockControl::boot_defaults(system.clock_control).freeze();

    let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
    let timer0: ErasedTimer = timg0.timer0.into();
    let timers = [OneShotTimer::new(timer0)];
    let timers = mk_static!([OneShotTimer<ErasedTimer>; 1], timers);
    esp_hal_embassy::init(&clocks, timers);

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

    let mut i2c0 = I2C::new_async(
        peripherals.I2C0,
        io.pins.gpio40,
        io.pins.gpio41,
        400.kHz(),
        &clocks,
    );

    let mut data = [0u8; 1];
    loop {
        println!("Reading (write_read) 1 byte from I2C device...");
        i2c0.write_read(0x68, &[0x00], &mut data).await.unwrap();
        println!("Read: {:02x?}", data[0]);
        Timer::after(Duration::from_millis(1000)).await;
    }
}

Cargo.toml:

[package]
name = "esp32s3-async-i2c"
version = "0.1.0"
authors = ["liebman <liebman@zod.com>"]
edition = "2021"
license = "MIT OR Apache-2.0"

[dependencies]
embassy-executor = { version = "0.5.0", features = ["task-arena-size-32768"] }
embassy-time = { version = "0.3.0", features = ["defmt", "generic-queue"]}
embedded-hal-async = { version = "1.0.0" }
esp-backtrace = { version = "0.13.0", features = [
    "esp32s3",
    "exception-handler",
    "panic-handler",
    "println",
] }
esp-hal = { version = "0.19.0", features = [ "esp32s3", "async" ] }
esp-hal-embassy = { version = "0.2.0", features = ["esp32s3"] }
esp-println = { version = "0.10.0", features = ["esp32s3"] }
static_cell = { version = "2.1", features = ["nightly"] }

[profile.dev]
# Rust debug is too slow.
# For debug builds always builds with some optimization
opt-level = "s"

[profile.release]
codegen-units = 1 # LLVM can perform better optimizations using a single thread
debug = 2
debug-assertions = false
incremental = false
lto = 'fat'
opt-level = 's'
overflow-checks = false

[patch.crates-io]
# this is where PR #1900 was merged
esp-backtrace = { git = "https://github.com/esp-rs/esp-hal.git", rev = "bb6e710327d44e47ef9018a7b1c4453094b29b11"}
esp-println = { git = "https://github.com/esp-rs/esp-hal.git", rev = "bb6e710327d44e47ef9018a7b1c4453094b29b11"}
esp-hal = { git = "https://github.com/esp-rs/esp-hal.git", rev = "bb6e710327d44e47ef9018a7b1c4453094b29b11"}
esp-hal-embassy = { git = "https://github.com/esp-rs/esp-hal.git", rev = "bb6e710327d44e47ef9018a7b1c4453094b29b11"}
jessebraham commented 2 months ago

cc @playfulFence

ProfFan commented 2 months ago

From what I see I2C does not have a HIL test, this should be fixed ASAP

Szybet commented 2 months ago

The same thing happens on esp32c6 :(

playfulFence commented 2 months ago

Yes, I've already fixed that, PR will be published in next 30 minutes

Szybet commented 2 months ago

Thanks!