aboutsummaryrefslogtreecommitdiff
path: root/libraries/Wire/src
diff options
context:
space:
mode:
authorMatthijs Kooijman <matthijs@stdin.nl>2020-06-11 15:39:45 +0200
committerMartino Facchin <m.facchin@arduino.cc>2020-06-11 15:39:52 +0200
commitf1fe5e8f08a54c053e12d84810a62e677a69294e (patch)
tree0821091f033c5c6250331c27ee8725480c280353 /libraries/Wire/src
parent38ff552087efdbe0d98a88e9f74bfeb5e1504997 (diff)
Wire: improve comments on timeout
Diffstat (limited to 'libraries/Wire/src')
-rw-r--r--libraries/Wire/src/Wire.cpp21
-rw-r--r--libraries/Wire/src/utility/twi.c4
2 files changed, 23 insertions, 2 deletions
diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp
index 81aca98..c407776 100644
--- a/libraries/Wire/src/Wire.cpp
+++ b/libraries/Wire/src/Wire.cpp
@@ -90,9 +90,28 @@ void TwoWire::setClock(uint32_t clock)
/***
* Sets the TWI timeout.
*
+ * This limits the maximum time to wait for the TWI hardware. If more time passes, the bus is assumed
+ * to have locked up (e.g. due to noise-induced glitches or faulty slaves) and the transaction is aborted.
+ * Optionally, the TWI hardware is also reset, which can be required to allow subsequent transactions to
+ * succeed in some cases (in particular when noise has made the TWI hardware think there is a second
+ * master that has claimed the bus).
+ *
+ * When a timeout is triggered, a flag is set that can be queried with `getWireTimeoutFlag()` and is cleared
+ * when `clearWireTimeoutFlag()` or `setWireTimeoutUs()` is called.
+ *
+ * Note that this timeout can also trigger while waiting for clock stretching or waiting for a second master
+ * to complete its transaction. So make sure to adapt the timeout to accomodate for those cases if needed.
+ * A typical timeout would be 25ms (which is the maximum clock stretching allowed by the SMBus protocol),
+ * but (much) shorter values will usually also work.
+ *
+ * In the future, a timeout will be enabled by default, so if you require the timeout to be disabled, it is
+ * recommended you disable it by default using `setWireTimeoutUs(0)`, even though that is currently
+ * the default.
+ *
* @param timeout a timeout value in microseconds, if zero then timeout checking is disabled
* @param reset_with_timeout if true then TWI interface will be automatically reset on timeout
* if false then TWI interface will not be reset on timeout
+
*/
void TwoWire::setWireTimeout(uint32_t timeout, bool reset_with_timeout){
twi_setTimeoutInMicros(timeout, reset_with_timeout);
@@ -101,7 +120,7 @@ void TwoWire::setWireTimeout(uint32_t timeout, bool reset_with_timeout){
/***
* Returns the TWI timeout flag.
*
- * @return true if timeout has occured
+ * @return true if timeout has occured since the flag was last cleared.
*/
bool TwoWire::getWireTimeoutFlag(void){
return(twi_manageTimeoutFlag(false));
diff --git a/libraries/Wire/src/utility/twi.c b/libraries/Wire/src/utility/twi.c
index b3096c6..5539633 100644
--- a/libraries/Wire/src/utility/twi.c
+++ b/libraries/Wire/src/utility/twi.c
@@ -413,7 +413,9 @@ void twi_stop(void)
// wait for stop condition to be exectued on bus
// TWINT is not set after a stop condition!
- volatile uint32_t counter = twi_timeout_us/10ul; // approximate the timeout
+ // We cannot use micros() from an ISR, so approximate the timeout with cycle-counted delays
+ const uint8_t us_per_loop = 8;
+ uint32_t counter = (twi_timeout_us + us_per_loop - 1)/us_per_loop; // Round up
while(TWCR & _BV(TWSTO)){
if(twi_timeout_us > 0ul){
if (counter > 0ul){