Skip to content

Commit d94ca66

Browse files
Update Wire per @chrisckc debugging (#1011)
Merge in changes @chrisckc debugged while working at 400khz on his own project. See #979 (comment)
1 parent e47e3c7 commit d94ca66

File tree

1 file changed

+25
-23
lines changed

1 file changed

+25
-23
lines changed

libraries/Wire/src/Wire.cpp

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -140,38 +140,50 @@ void TwoWire::begin(uint8_t addr) {
140140
_running = true;
141141
}
142142

143+
// See: https://github.com/earlephilhower/arduino-pico/issues/979#issuecomment-1328237128
144+
#pragma GCC push_options
145+
#pragma GCC optimize ("O0")
143146
void TwoWire::onIRQ() {
144147
// Make a local copy of the IRQ status up front. If it changes while we're
145148
// running the IRQ callback will fire again after returning. Avoids potential
146149
// race conditions
147-
volatile uint32_t irqstat = _i2c->hw->intr_stat;
150+
uint32_t irqstat = _i2c->hw->intr_stat;
151+
if (irqstat == 0) {
152+
return;
153+
}
148154

149155
// First, pull off any data available
150156
if (irqstat & (1 << 2)) {
151157
// RX_FULL
152-
if (_slaveStartDet && (_buffLen < (int)sizeof(_buff))) {
158+
if (_buffLen < (int)sizeof(_buff)) {
153159
_buff[_buffLen++] = _i2c->hw->data_cmd & 0xff;
154160
} else {
155161
_i2c->hw->data_cmd;
156162
}
157163
}
158-
// RESTART_DET
159-
if (irqstat & (1 << 12)) {
160-
if (_onReceiveCallback && _buffLen) {
161-
_onReceiveCallback(_buffLen);
164+
// RD_REQ
165+
if (irqstat & (1 << 5)) {
166+
if (_onRequestCallback) {
167+
_onRequestCallback();
162168
}
163-
_buffLen = 0;
164-
_buffOff = 0;
165-
_slaveStartDet = false;
166-
_i2c->hw->clr_restart_det;
169+
_i2c->hw->clr_rd_req;
170+
}
171+
// TX_ABRT
172+
if (irqstat & (1 << 6)) {
173+
_i2c->hw->clr_tx_abrt;
167174
}
168175
// START_DET
169176
if (irqstat & (1 << 10)) {
170-
_buffLen = 0;
171-
_buffOff = 0;
172177
_slaveStartDet = true;
173178
_i2c->hw->clr_start_det;
174179
}
180+
// RESTART_DET
181+
if (irqstat & (1 << 12)) {
182+
if (_onReceiveCallback && _buffLen) {
183+
_onReceiveCallback(_buffLen);
184+
}
185+
_i2c->hw->clr_restart_det;
186+
}
175187
// STOP_DET
176188
if (irqstat & (1 << 9)) {
177189
if (_onReceiveCallback && _buffLen) {
@@ -182,18 +194,8 @@ void TwoWire::onIRQ() {
182194
_slaveStartDet = false;
183195
_i2c->hw->clr_stop_det;
184196
}
185-
// TX_ABRT
186-
if (irqstat & (1 << 6)) {
187-
_i2c->hw->clr_tx_abrt;
188-
}
189-
// RD_REQ
190-
if (irqstat & (1 << 5)) {
191-
if (_onRequestCallback) {
192-
_onRequestCallback();
193-
}
194-
_i2c->hw->clr_rd_req;
195-
}
196197
}
198+
#pragma GCC pop_options
197199

198200
void TwoWire::end() {
199201
if (!_running) {

0 commit comments

Comments
 (0)