mirror of
https://github.com/adafruit/Adafruit_SSD1306.git
synced 2026-07-27 20:05:50 +00:00
Add Wire.setWireTimeout to avoid I2C bus hangs (closes #288)
If the I2C bus stops responding mid-transaction (noise, the display becomes disconnected, etc.), the underlying Wire library spins in an indefinite loop and the host MCU effectively hangs. The Arduino AVR core fixed this in ArduinoCore-avr@deea929 by exposing setWireTimeout(); cores that implement it define WIRE_HAS_TIMEOUT so callers can detect the feature at compile time. Use that detection: when periphBegin owns the wire->begin() call, follow it with a 25 ms timeout + reset on timeout. We only touch Wire's configuration when we performed the begin() ourselves; if the caller managed Wire externally, leave their configuration untouched. No behavioural change on cores without WIRE_HAS_TIMEOUT (the entire block is compiled out).
This commit is contained in:
+12
-1
@@ -522,8 +522,19 @@ bool Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, bool reset,
|
|||||||
// function if it has unusual circumstances (e.g. TWI variants that
|
// function if it has unusual circumstances (e.g. TWI variants that
|
||||||
// can accept different SDA/SCL pins, or if two SSD1306 instances
|
// can accept different SDA/SCL pins, or if two SSD1306 instances
|
||||||
// with different addresses -- only a single begin() is needed).
|
// with different addresses -- only a single begin() is needed).
|
||||||
if (periphBegin)
|
if (periphBegin) {
|
||||||
wire->begin();
|
wire->begin();
|
||||||
|
#ifdef WIRE_HAS_TIMEOUT
|
||||||
|
// Avoid indefinite hangs in the Wire library when the I2C bus stops
|
||||||
|
// responding (e.g. SDA/SCL noise or the display disconnects). The
|
||||||
|
// setWireTimeout() API is exposed by Arduino cores that define
|
||||||
|
// WIRE_HAS_TIMEOUT (Arduino AVR core >= 1.8.6, see ArduinoCore-avr#42).
|
||||||
|
// We only set the timeout when we owned the begin() call -- if the
|
||||||
|
// caller managed Wire themselves, leave their configuration untouched.
|
||||||
|
// See Adafruit_SSD1306 issue #288.
|
||||||
|
wire->setWireTimeout(25000 /* us */, true /* reset on timeout */);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
} else { // Using one of the SPI modes, either soft or hardware
|
} else { // Using one of the SPI modes, either soft or hardware
|
||||||
pinMode(dcPin, OUTPUT); // Set data/command pin as output
|
pinMode(dcPin, OUTPUT); // Set data/command pin as output
|
||||||
pinMode(csPin, OUTPUT); // Same for chip select
|
pinMode(csPin, OUTPUT); // Same for chip select
|
||||||
|
|||||||
Reference in New Issue
Block a user