From deea9293201dbab724b6b0519c35ddba3e6b92d9 Mon Sep 17 00:00:00 2001 From: Greyson Christoforo Date: Wed, 28 Feb 2018 20:59:45 +0000 Subject: Introduce non compulsory Wire timeout move timout handling into its own function change timeout from milliseconds to microseconds don't forget operating slave address or the bitrate when we reset because of a timeout Co-Authored-By: Witold Markowski fix delay datatype uint16_t --> uint32_t Update libraries/Wire/src/utility/twi.c fix mix up using TWBR instea of TWAR! Co-Authored-By: Matthijs Kooijman Update libraries/Wire/src/utility/twi.c fix 2nd TWBR/TWAR mixup Co-Authored-By: Matthijs Kooijman twi_stop() should use the same timeout as everywhere else all while loops are now protected by timeouts Revert "twi_stop() should use the same timeout as everywhere else" This reverts commit 68fe5f1dae1bb41183bb37eeda3fb453394a580c. make timeout counter volatile rename timeout function for improved clarity - resetting the twi interface on timeouts is now optional - timeouts in the ISR are no longer hardcoded and now obey the set timeout value - a user-readable flag is now set whenever a timeout occurs - the user can clear this flag whenever they like --- libraries/Wire/src/Wire.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'libraries/Wire/src/Wire.cpp') diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index 58916ce..b446f9a 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -18,6 +18,7 @@ Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts Modified 2017 by Chuck Todd (ctodd@cableone.net) to correct Unconfigured Slave Mode reboot + Modified 2020 by Greyson Christoforo (grey@christoforo.net) to implement timeouts */ extern "C" { @@ -86,6 +87,33 @@ void TwoWire::setClock(uint32_t clock) twi_setFrequency(clock); } +/*** + * Sets the TWI timeout. + * + * @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::setWireTimeoutUs(uint32_t timeout, bool reset_with_timeout){ + twi_setTimeoutInMicros(timeout, reset_with_timeout); +} + +/*** + * Returns the TWI timeout flag. + * + * @return true if timeout has occured + */ +bool TwoWire::getWireTimeoutFlag(void){ + return(twi_manageTimeoutFlag(false)); +} + +/*** + * Clears the TWI timeout flag. + */ +void TwoWire::clearWireTimeoutFlag(void){ + twi_manageTimeoutFlag(true); +} + uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop) { if (isize > 0) { -- cgit v1.2.3-18-g5258 From 38ff552087efdbe0d98a88e9f74bfeb5e1504997 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 11 Jun 2020 15:36:44 +0200 Subject: Wire: add sensible defaults to setWireTimeout --- libraries/Wire/src/Wire.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libraries/Wire/src/Wire.cpp') diff --git a/libraries/Wire/src/Wire.cpp b/libraries/Wire/src/Wire.cpp index b446f9a..81aca98 100644 --- a/libraries/Wire/src/Wire.cpp +++ b/libraries/Wire/src/Wire.cpp @@ -94,7 +94,7 @@ void TwoWire::setClock(uint32_t clock) * @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::setWireTimeoutUs(uint32_t timeout, bool reset_with_timeout){ +void TwoWire::setWireTimeout(uint32_t timeout, bool reset_with_timeout){ twi_setTimeoutInMicros(timeout, reset_with_timeout); } -- cgit v1.2.3-18-g5258 From f1fe5e8f08a54c053e12d84810a62e677a69294e Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Thu, 11 Jun 2020 15:39:45 +0200 Subject: Wire: improve comments on timeout --- libraries/Wire/src/Wire.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'libraries/Wire/src/Wire.cpp') 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)); -- cgit v1.2.3-18-g5258