I2C ReSTART returns Success (#2141)

* 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.

* add comments

add comments

* 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.
This commit is contained in:
chuck todd 2018-12-03 08:16:43 -07:00 committed by Me No Dev
parent 8aa6e2e143
commit 7a332864ab
2 changed files with 23 additions and 13 deletions

View File

@ -154,14 +154,15 @@ void TwoWire::beginTransmission(uint16_t address)
uint8_t TwoWire::endTransmission(bool sendStop) // Assumes Wire.beginTransaction(), Wire.write() uint8_t TwoWire::endTransmission(bool sendStop) // Assumes Wire.beginTransaction(), Wire.write()
{ {
if(transmitting == 1) { if(transmitting == 1) {
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 // txlength is howmany bytes in txbuffer have been use
last_error = writeTransmission(txAddress, &txBuffer[txQueued], txLength - txQueued, sendStop);
if(last_error == I2C_ERROR_CONTINUE){
txQueued = txLength; 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 { } else {
last_error = I2C_ERROR_NO_BEGIN; last_error = I2C_ERROR_NO_BEGIN;
@ -170,7 +171,7 @@ uint8_t TwoWire::endTransmission(bool sendStop) // Assumes Wire.beginTransactio
txIndex = 0; txIndex = 0;
txLength = 0; txLength = 0;
transmitting = 0; transmitting = 0;
return last_error; 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 /* @stickBreaker 11/2017 fix for ReSTART timeout, ISR
@ -191,12 +192,19 @@ uint8_t TwoWire::requestFrom(uint16_t address, uint8_t size, bool sendStop)
last_error = readTransmission(address, &rxBuffer[cnt], size, sendStop, &cnt); last_error = readTransmission(address, &rxBuffer[cnt], size, sendStop, &cnt);
rxIndex = 0; rxIndex = 0;
rxLength = rxQueued;
rxQueued = 0; rxLength = cnt;
txQueued = 0; // the SendStop=true will restart all Queueing
if(last_error != I2C_ERROR_OK){ 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; cnt = 0;
} }
return cnt; return cnt;
} }

View File

@ -67,12 +67,13 @@ protected:
public: public:
TwoWire(uint8_t bus_num); TwoWire(uint8_t bus_num);
~TwoWire(); ~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 void setClock(uint32_t frequency); // change bus clock without initing hardware
size_t getClock(); // current bus clock rate in hz 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(); uint16_t getTimeOut();
uint8_t lastError(); 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() 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 to a function, this allow reporting if bus cannot be initialized, Wire.begin() can be used to recover
a hung bus busy condition. a hung bus busy condition.