From 2fc395cb04580c2b4abdad9c75af23dff174c167 Mon Sep 17 00:00:00 2001 From: chuck todd Date: Thu, 29 Nov 2018 13:31:42 -0700 Subject: [PATCH 1/3] Don't Return I2C_ERROR_CONTINUE on ReSTART ReSTART operations on the ESP32 have to be handled differently than on AVR chips, so ReSTART operations(`Wire.endTransmission(false), Wire.requestFrom(id,size,false);` are queued until a STOP is send (`Wire.endTransmission(TRUE), Wire.endTransmission(), Wire.requestFrom(id,size), Wire.requestFrom(id,size,TRUE)). To indicate the queuing I had used `I2C_ERROR_CONTINUE`, this caused compatibility issues with the existing Arduino I2C Code base. So, back to Lying to the public(for their own good of course) about success! This update just returns `I2C_ERROR_OK` on ReSTART commands. --- libraries/Wire/src/Wire.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index 87ed627b780..de12b4c8d78 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -170,7 +170,7 @@ uint8_t TwoWire::endTransmission(bool sendStop) // Assumes Wire.beginTransactio txIndex = 0; txLength = 0; transmitting = 0; - return last_error; + return (last_error == I2C_ERROR_CONTINUE)?I2C_ERROR_OK:last_error; // Don't return Continue for compatibilty. } /* @stickBreaker 11/2017 fix for ReSTART timeout, ISR @@ -191,12 +191,23 @@ uint8_t TwoWire::requestFrom(uint16_t address, uint8_t size, bool sendStop) last_error = readTransmission(address, &rxBuffer[cnt], size, sendStop, &cnt); rxIndex = 0; - rxLength = rxQueued; - rxQueued = 0; - txQueued = 0; // the SendStop=true will restart all Queueing - if(last_error != I2C_ERROR_OK){ + + if(cnt == size){ // full recieve + rxLength = rxQueued; + } else { // handle partial receive + rxLength = rxQueued - size + cnt; + } + + if( last_error != I2C_ERROR_CONTINUE){ // not a buffered ReSTART operation + // so this operation actually moved data, queuing is done. + rxQueued = 0; + txQueued = 0; // the SendStop=true will restart all Queueing or error condition + } + + if(last_error != I2C_ERROR_OK){ // ReSTART on read does not return any data cnt = 0; } + return cnt; } From 1de3dda9283f888483dc238499cd56672663362d Mon Sep 17 00:00:00 2001 From: chuck todd Date: Thu, 29 Nov 2018 13:51:54 -0700 Subject: [PATCH 2/3] add comments add comments --- libraries/Wire/src/Wire.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/Wire/src/Wire.h b/libraries/Wire/src/Wire.h index 34bdd60a8f4..031ea3e5740 100644 --- a/libraries/Wire/src/Wire.h +++ b/libraries/Wire/src/Wire.h @@ -67,12 +67,13 @@ class TwoWire: public Stream public: TwoWire(uint8_t bus_num); ~TwoWire(); - bool begin(int sda=-1, int scl=-1, uint32_t frequency=0); + bool begin(int sda=-1, int scl=-1, uint32_t frequency=0); // returns true, if successful init of i2c bus + // calling will attemp to recover hung bus void setClock(uint32_t frequency); // change bus clock without initing hardware size_t getClock(); // current bus clock rate in hz - void setTimeOut(uint16_t timeOutMillis); + void setTimeOut(uint16_t timeOutMillis); // default timeout of i2c transactions is 50ms uint16_t getTimeOut(); uint8_t lastError(); @@ -137,6 +138,7 @@ extern TwoWire Wire1; /* +V1.0.2 30NOV2018 stop returning I2C_ERROR_CONTINUE on ReSTART operations, regain compatibility with Arduino libs V1.0.1 02AUG2018 First Fix after release, Correct ReSTART handling, change Debug control, change begin() to a function, this allow reporting if bus cannot be initialized, Wire.begin() can be used to recover a hung bus busy condition. From b80511795262bf2d9833398386a60c20e2ed8d74 Mon Sep 17 00:00:00 2001 From: chuck todd Date: Sun, 2 Dec 2018 11:02:44 -0700 Subject: [PATCH 3/3] Change Return error for ReSTART operation to I2C_ERROR_OK This change restores compatibility with pre-existing Arduino Libraries. The ReSTART queuing operations are hidden behind the scenes. Wire.endTransmission(id,len,FALSE); will know return I2C_ERROR_OK instead of I2C_ERROR_CONTINUE, Wire.lastError() will return the true condition of I2C_ERROR_CONTINUE. --- libraries/Wire/src/Wire.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index de12b4c8d78..bc580147800 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -154,14 +154,15 @@ void TwoWire::beginTransmission(uint16_t address) uint8_t TwoWire::endTransmission(bool sendStop) // Assumes Wire.beginTransaction(), Wire.write() { if(transmitting == 1) { + // txlength is howmany bytes in txbuffer have been use last_error = writeTransmission(txAddress, &txBuffer[txQueued], txLength - txQueued, sendStop); - rxIndex = 0; - rxLength = rxQueued; - rxQueued = 0; - txQueued = 0; // the SendStop=true will restart all Queueing if(last_error == I2C_ERROR_CONTINUE){ - // txlength is howmany bytes in txbuffer have been use txQueued = txLength; + } else if( last_error == I2C_ERROR_OK){ + rxIndex = 0; + rxLength = rxQueued; + rxQueued = 0; + txQueued = 0; // the SendStop=true will restart all Queueing } } else { last_error = I2C_ERROR_NO_BEGIN; @@ -170,7 +171,7 @@ uint8_t TwoWire::endTransmission(bool sendStop) // Assumes Wire.beginTransactio txIndex = 0; txLength = 0; transmitting = 0; - return (last_error == I2C_ERROR_CONTINUE)?I2C_ERROR_OK:last_error; // Don't return Continue for compatibilty. + return (last_error == I2C_ERROR_CONTINUE)?I2C_ERROR_OK:last_error; // Don't return Continue for compatibility. } /* @stickBreaker 11/2017 fix for ReSTART timeout, ISR @@ -192,11 +193,7 @@ uint8_t TwoWire::requestFrom(uint16_t address, uint8_t size, bool sendStop) last_error = readTransmission(address, &rxBuffer[cnt], size, sendStop, &cnt); rxIndex = 0; - if(cnt == size){ // full recieve - rxLength = rxQueued; - } else { // handle partial receive - rxLength = rxQueued - size + cnt; - } + rxLength = cnt; if( last_error != I2C_ERROR_CONTINUE){ // not a buffered ReSTART operation // so this operation actually moved data, queuing is done.