esp-rs / esp-idf-hal

embedded-hal implementation for Rust on ESP32 and ESP-IDF
https://docs.esp-rs.org/esp-idf-hal/
Apache License 2.0
470 stars 171 forks source link

[BUG] SPI sleep die at `async fn with_completion()` #463

Closed xiaguangbo closed 3 months ago

xiaguangbo commented 4 months ago

Running 10/s, can cause problem in minutes or seconds. Won't trigger watchdog, but tokio won't run tasks. In async fn with_completion and async fn spi_transmit_async ... fut adding log printing wil greatly reduce the probability of occurrence. If change the way use SPI, be no occurrence problem. I'm not sure which sentence has problem for the time being in spi_transmit_async.

No problem:

let mut dbuf = [0u8; 16];

for i in 0..8 {
    self.spi
    .transaction_async(&mut [
        Operation::Write(&[0xc0 + (i * 2) as u8]),
        Operation::Write(&dbuf[i * 2..i * 2 + 2]),
    ])
    .await
    .unwrap();
}

Have problem:

let mut dbuf = [0u8; 16];

self.spi
    .transaction_async(&mut [
        Operation::Write(&[0xc0]),
        Operation::Write(&dbuf[0..16]),
    ])
    .await
    .unwrap();

spi.rs:

async fn with_completion<F, D>(fut: F, dtor: D) -> F::Output
where
    F: Future,
    D: FnMut(bool),
{
    struct Completion<D>
    where
        D: FnMut(bool),
    {
        dtor: D,
        completed: bool,
    }

    impl<D> Drop for Completion<D>
    where
        D: FnMut(bool),
    {
        fn drop(&mut self) {
            (self.dtor)(self.completed);
        }
    }

    let mut completion = Completion {
        dtor,
        completed: false,
    };

    let result = fut.await; // There is acertain chance of stop.

    completion.completed = true;

    result
}
xiaguangbo commented 3 months ago

use sync api