Fix for deadlock conditions after i2c bus errors #23
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Hello. I'm working on getting my project, Modulo (www.modulo.co) working with the Arduino Zero. Modulo uses hot plugging of i2c devices, so it tends to stress test handling of i2c bus errors. I found two places in SERCOM.cpp where incorrect handling of error conditions can cause a deadlock to occur. This pull request includes simple fixes for both of them.
The first occurs when an addressed device simply doesn't respond. This can be easily reproduced by doing a Wire.requestFrom() to an address that doesn't exist. Without the fix the arduino will completely lock up. With the fix, requestFrom returns an error. The bug is that it waits until the SB (slave on bus) bit is set in the INTFLAGS register, but when a nack occurs that never happens so we're stuck in an infinite loop. The fix is to also look for the MB flag to be set. If it is, issue a stop condition and return.
The second happens when a bus error (ie, an illegal stop condition) occurs while sending data as a master. This can be reproduced by connecting/disconnecting the SDA and SCL lines while i2c communication is in progress. In that case we are waiting for the MB (master on bus) flag to be set. When a bus error occurs that never happens, so again we end up in an infinite loop. The fix here is to also look for the BUSERR flag to be set. If it is, return an error condition.
Please let me know if there's any additional information I can provide on the problems or the fixes. Thanks.