Skip to content

Commit 1d70883

Browse files
committed
fix(twi): fails on repeated start condition
reproduction: https://wokwi.com/arduino/projects/306115576172905024 minimal reproduction code: ```cpp #include <Wire.h> void setup() { Serial.begin(115200); Wire.begin(); Wire.beginTransmission(0x68); Wire.write( 0x3B); Wire.endTransmission( false); // <---- Fails after this auto n = Wire.requestFrom(0x68, 6); if (n == 6) { int16_t AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L) int16_t AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L) int16_t AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) Serial.print( "AcX = "); Serial.print( AcX); Serial.print( " | AcY = "); Serial.print( AcY); Serial.print( " | AcZ = "); Serial.print( AcZ); Serial.println(); } else { Serial.println( "--------- ERROR ---------"); } } void loop() {} ```
1 parent ad40366 commit 1d70883

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

src/peripherals/twi.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export class NoopTWIEventHandler implements TWIEventHandler {
9494

9595
export class AVRTWI {
9696
public eventHandler: TWIEventHandler = new NoopTWIEventHandler(this);
97+
private busy = false;
9798

9899
// Interrupts
99100
private TWI: AVRInterruptConfig = {
@@ -112,18 +113,23 @@ export class AVRTWI {
112113
this.cpu.clearInterruptByFlag(this.TWI, value);
113114
this.cpu.updateInterruptEnable(this.TWI, value);
114115
const { status } = this;
115-
if (clearInt && value & TWCR_TWEN) {
116+
if (clearInt && value & TWCR_TWEN && !this.busy) {
116117
const twdrValue = this.cpu.data[this.config.TWDR];
117118
this.cpu.addClockEvent(() => {
118119
if (value & TWCR_TWSTA) {
120+
this.busy = true;
119121
this.eventHandler.start(status !== STATUS_TWI_IDLE);
120122
} else if (value & TWCR_TWSTO) {
123+
this.busy = true;
121124
this.eventHandler.stop();
122125
} else if (status === STATUS_START || status === STATUS_REPEATED_START) {
126+
this.busy = true;
123127
this.eventHandler.connectToSlave(twdrValue >> 1, twdrValue & 0x1 ? false : true);
124128
} else if (status === STATUS_SLAW_ACK || status === STATUS_DATA_SENT_ACK) {
129+
this.busy = true;
125130
this.eventHandler.writeByte(twdrValue);
126131
} else if (status === STATUS_SLAR_ACK || status === STATUS_DATA_RECEIVED_ACK) {
132+
this.busy = true;
127133
const ack = !!(value & TWCR_TWEA);
128134
this.eventHandler.readByte(ack);
129135
}
@@ -153,15 +159,18 @@ export class AVRTWI {
153159
}
154160

155161
completeStart() {
162+
this.busy = false;
156163
this.updateStatus(this.status === STATUS_TWI_IDLE ? STATUS_START : STATUS_REPEATED_START);
157164
}
158165

159166
completeStop() {
167+
this.busy = false;
160168
this.cpu.data[this.config.TWCR] &= ~TWCR_TWSTO;
161169
this.updateStatus(STATUS_TWI_IDLE);
162170
}
163171

164172
completeConnect(ack: boolean) {
173+
this.busy = false;
165174
if (this.cpu.data[this.config.TWDR] & 0x1) {
166175
this.updateStatus(ack ? STATUS_SLAR_ACK : STATUS_SLAR_NACK);
167176
} else {
@@ -170,10 +179,12 @@ export class AVRTWI {
170179
}
171180

172181
completeWrite(ack: boolean) {
182+
this.busy = false;
173183
this.updateStatus(ack ? STATUS_DATA_SENT_ACK : STATUS_DATA_SENT_NACK);
174184
}
175185

176186
completeRead(value: u8) {
187+
this.busy = false;
177188
const ack = !!(this.cpu.data[this.config.TWCR] & TWCR_TWEA);
178189
this.cpu.data[this.config.TWDR] = value;
179190
this.updateStatus(ack ? STATUS_DATA_RECEIVED_ACK : STATUS_DATA_RECEIVED_NACK);

0 commit comments

Comments
 (0)