raspberrypi / pico-sdk

BSD 3-Clause "New" or "Revised" License
3.74k stars 929 forks source link

i2c lockup #2025

Open peterharperuk opened 16 hours ago

peterharperuk commented 16 hours ago

If you run the i2c bus_scan example on Pico 2 with or without anything connected and ONLY stdout USB enabled then the device invariably locks up. It seems to get stuck in the loop waiting for an abort which never seems to happen! It works fine if sdio uart is enabled?! And Pico 1 seems ok.

        i2c->hw->data_cmd =
                bool_to_bit(first && i2c->restart_on_next) << I2C_IC_DATA_CMD_RESTART_LSB |
                bool_to_bit(last && !nostop) << I2C_IC_DATA_CMD_STOP_LSB |
                I2C_IC_DATA_CMD_CMD_BITS; // -> 1 for read

        do {
            abort_reason = i2c->hw->tx_abrt_source;
            abort = (bool) i2c->hw->clr_tx_abrt;
            if (timeout_check) {
                timeout = timeout_check(ts, false);
                abort |= timeout;
            }
        } while (!abort && !i2c_get_read_available(i2c)); <-- NEVER EXITS

Usually the abort seems to happen after around 130 iterations. If I repeat the command in the loop after 200 iterations or so, it seems to fix the problem.

peterharperuk commented 16 hours ago

It seems to happen eventually even if stdio is disabled. Just seems that stdout usb makes it happen much quicker. But enabling stdio uart stops it happening?!

peterharperuk commented 14 hours ago

My theory is that as we're clearing the abort interrupt 100s of times while checking for an abort, occasionally this leads us to lose the interrupt on the next run. If we only clear the abort interrupt when required, it seems to fix the lockup.