In terms of how to handle requestFrom() and available(), the issue I see is that there is no API documentation that defines how requestFrom() is supposed to behave.
All it says is that it returns: "the number of bytes returned from the slave device"
It does not specify if it is normally the requested number of bytes or even if the call is synchronous/blocking until the expected data arrives.
This is incomplete and should be updated to further define the behavior.
In a single master environment, with the existing AVR code (not sure how it is handled in the other cores), it should always be the number of bytes requested.
But even with current AVR code that "waits" for all the bytes, in multi master (assuming the library can really handle multi masters) it can return early with less than the requested bytes if another master jumps in and uses the bus.
And if in a multi-master environment, even though the requestFrom() will return early, eventually the remaining bytes will still come in. (they will be handled by the ISR and stuffed into the twi private RX buffer).
So the value of available() is really in multi-master environments, where requestFrom() can return early but the rest of the bytes will eventually come in.
This will be the only way to know when the rest of the bytes from a premature return of requestFrom() actually arrive.
I would actually prefer that the Wire library - which sits on top of the twi code, was smarter and would hide this early twi code return and issue another request to the twi code to complete the read so that even in a multi-master environment, the Wire.requestFrom() never returned until all the bytes were received.
This would ensure that the behavior is consistent regardless of whether being used in multi-master environment.
In other words there should be some way through the API to tell the Wire code to not return back until either all the bytes were received or there was a fatal error.
Losing the bus in a multi-master environment is not a fatal error and should be hidden from the application.
RayLivingston:
I would be very interested in hearing what you find there. I think I may be having the same problem recently. Is this perhaps on a Due?
Regards,
Ray L.
It is AVR.
Koepel:
bperrybap, do you use the newest Arduino IDE 1.6.9 ?
The I2C was improved with version 1.6.6 for collisions and timing. Since 1.6.6 I can use I2C without problems between two Arduino boards.
I was using 1.6.7
While I could have missed it, I looked at the githib repo and didn't see any code updates that looked related to this specific condition.
I'll go back and take another look and even try the latest 1.6.9 IDE.
The state status is: TW_MR_ARB_LOST, which is the same state value as TW_MT_ARB_LOST
The current code doesn't really handle TW_MR_ARB_LOST (which is lost arbitration during relieves) and handles it the same way as lost arbitration during transmits. And that may be part of the problem.
I'm assuming that the AVR dropped off the bus and flipped into slave mode and is now waiting to see a STOP from the "other master" before it will ever jump back on the bus.
The issue is that a STOP will never occur in this case.
In 1.6.0 and later I can recover by doing an end() then begin() and then a dummy address phase.
But I'm looking for a solution in the actual library.
A I2C device that ACKs when the Master is reading is nuts. I don't blame the Wire library if the Wire library goes haywire.
The device is an i2c LCD:
I see this as an issue.
The current code will hang and lock up the AVR in this situation and never recover.
I don't like code that does not gracefully handle and recover from errors.
Seems like there should be sort of timeout that should allow recovery from this condition.
Either the h/w or the s/w is broken and so the s/w would need to be updated to handle this situation
I need to start another thread on this but I don't know where to put it.
Any suggestions?
--- bill