• chuck todd's avatar
    Wire ReSTART fix, with others (#1717) · b05430cf
    chuck todd authored
    * ReSTART fix, Sequencing fix
    
    pr #1665 introduce a problem with ReSTART, when solving this problem I found an interaction between the TxFifo refill, RxFifo empty and CMD[] fill.  during certain sequences a dataqueue command would be skipped, this skipping resulted in a mismatch between the contents of the TxFifo and the i2c command sequence.  The problem manifested as an ACK error. 
    In addition to this required bug fix I propose:
    * `Wire.begin()` be changed from a `void` to a `bool` this will allow the reset functionality of `Wire.begin()` to be reported.  Currently `Wire.begin()` attempts to reset the i2c Peripheral, but cannot report success/failure.
    * `Wire.busy()` be added. this `bool` function returns the hardware status of the bus. This status can be use in multi-master environments for application level interleaving of commands, also in single master environment, it can be used to detect a 'hung' bus.  With the functional change to `Wire.begin()` this allows app level recover of a hung bus.
    * `Wire.lastError()` value updated for all errors, previously when interleaving `Wire.endTransmission(false)` and `Wire.readTransmission(false)`, the 128 byte `Wire.write()` buffer was exhausted without generating and error(very exotic). I discovered this error when I created a sequence of directed reads to a EEPROM. Each directed read used 2 bytes of the 128 byte `write()` buffer, so after 64 consecutive ReSTART writes with ReSTART reads, `Wire()`  had no room to record the directed address bytes.  It generated just a NAK check without setting the EEPROMs internal register address.  The succeeding ReSTART read succeeded at incorrect address.
    * Changes to the HAL layer:
    ** added `i2cGetStatus()` which returns the i2c peripheral status word, used to detect bus_busy currently
    ** added `i2cDebug()` programmatic control of debug buffer output
    ** changed `i2cAddQueue()` to allow data_only queue element this will allow a i2c transaction to use multiple data pointers.
    ** removed direct access to DumpInts(), DumpI2c() from app, use i2cDebug() to set trigger points 
     
    *
    
    * Update esp32-hal-i2c.c
    
    * Update Wire.cpp
    
    * ReSTART, Sequencing
    
    pr #1665 introduce a problem with ReSTART, when solving this problem I found an interaction between the TxFifo refill, RxFifo empty and CMD[] fill.  during certain sequences a dataqueue command would be skipped, this skipping resulted in a mismatch between the contents of the TxFifo and the i2c command sequence.  The problem manifested as an ACK error. 
    In addition to this required bug fix I propose:
    * `Wire.begin()` be changed from a `void` to a `bool` this will allow the reset functionality of `Wire.begin()` to be reported.  Currently `Wire.begin()` attempts to reset the i2c Peripheral, but cannot report success/failure.
    * `Wire.busy()` be added. this `bool` function returns the hardware status of the bus. This status can be use in multi-master environments for application level interleaving of commands, also in single master environment, it can be used to detect a 'hung' bus.  With the functional change to `Wire.begin()` this allows app level recover of a hung bus.
    * `Wire.lastError()` value updated for all errors, previously when interleaving `Wire.endTransmission(false)` and `Wire.readTransmission(false)`, the 128 byte `Wire.write()` buffer was exhausted without generating and error(very exotic). I discovered this error when I created a sequence of directed reads to a EEPROM. Each directed read used 2 bytes of the 128 byte `write()` buffer, so after 64 consecutive ReSTART writes with ReSTART reads, `Wire()`  had no room to record the directed address bytes.  It generated just a NAK check without setting the EEPROMs internal register address.  The succeeding ReSTART read succeeded at incorrect address.
    * Changes to the HAL layer:
    ** added `i2cGetStatus()` which returns the i2c peripheral status word, used to detect bus_busy currently
    ** added `i2cDebug()` programmatic control of debug buffer output
    ** changed `i2cAddQueue()` to allow data_only queue element this will allow a i2c transaction to use multiple data pointers.
    ** removed direct access to DumpInts(), DumpI2c() from app, use i2cDebug() to set trigger points 
     
    *
    
    * Forgot DebugFlags Return
    
    @andriyadi found this, total brain fade on my part.
    b05430cf
Wire.h 4.68 KB