8000 Intermittent i2c slave mode errors · Issue #1100 · earlephilhower/arduino-pico · GitHub
  • [go: up one dir, main page]

    Skip to content
    Intermittent i2c slave mode errors #1100
    @chrisckc

    Description

    @chrisckc

    This is a continuation of this issue:
    Intermittent i2c errors, byte count incorrect and missing bytes in onReceive interrupt handler
    #979

    I noticed that the changes to Wire.cpp introduced to make improvements to the above issue (I2C slave receiving data) seem to have broken the ability of a Pico in I2C slave mode to respond to I2C requests.

    The changes made have improved the error rate for receiving data, which according to my tests dropped down to around 0.027% at 1MHz I2C clock, however the I2C "Repeated Start Condition" now does not seem to work properly.

    I have tested Wire.cpp from the last commit before the recent changes (June) and this issue does not exist, just the original data reception issue.

    I have only recently noticed this when I created a new test harness which sends data both ways between 2 Pico's, previously the slave Pico was only receiving data, not responding to any I2C requests.

    The new test harness projects have been added to the original test harness repo:
    https://github.com/chrisckc/TestHarness-I2C/tree/master/I2C_receiver-new
    https://github.com/chrisckc/TestHarness-I2C/tree/master/I2c_sender-new
    These are based on sending a 255 byte buffer of sequential bytes back and forth between the 2 Pico's

    The issue responding to I2C requests is due to this section of the onIRQ() function inside Wire.cpp:

        // RESTART_DET
        if (irqstat & (1 << 12)) {
            if (_onReceiveCallback && _buffLen) {
                _onReceiveCallback(_buffLen);
            }
            _i2c->hw->clr_restart_det;
        }
    

    To fix the issue, the above section needs to be changed to this to allow the "Repeated Start Condition" to be handled correctly, as in the original code. The "Repeated Start Condition" is used by the master when making I2C requests to prevent other devices from grabbing the bus between the transfer of the read command from the master to the slave and its response to the master.

        // RESTART_DET
        if (irqstat & (1 << 12)) {
            if (_onReceiveCallback && _buffLen) {
                _onReceiveCallback(_buffLen);
            }
            _buffLen = 0;
            _buffOff = 0;
            _slaveStartDet = false;
            _i2c->hw->clr_restart_det;
        }
    

    Metadata

    Metadata

    Assignees

    No one assigned

      Labels

      No labels
      No labels

      Projects

      No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

        0