Skip to content

Commit 3ecb32c

Browse files
committed
Prevent I2C Bus locks and wrong data being sent on retry
1 parent 45f5449 commit 3ecb32c

File tree

1 file changed

+43
-39
lines changed

1 file changed

+43
-39
lines changed

cores/esp32/esp32-hal-i2c.c

+43-39
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ int i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uin
8989
uint8_t willSend = (dataLen > 32)?32:dataLen;
9090
uint8_t dataSend = willSend;
9191

92+
i2cResetFiFo(i2c);
93+
9294
//CMD START
9395
i2cSetCmd(i2c, 0, I2C_CMD_RSTART, 0, false, false, false);
9496

@@ -124,33 +126,31 @@ int i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uin
124126

125127
//WAIT Transmission
126128
while(1) {
129+
//Bus failed (maybe check for this while waiting?
130+
if(i2c->dev->int_raw.arbitration_lost) {
131+
//log_e("Bus Fail! Addr: %x", address >> 1);
132+
return 4;
133+
}
134+
135+
//Bus timeout
136+
if(i2c->dev->int_raw.time_out) {
137+
//log_e("Bus Timeout! Addr: %x", address >> 1);
138+
return 3;
139+
}
140+
141+
//Transmission did not finish and ACK_ERR is set
142+
if(i2c->dev->int_raw.ack_err) {
143+
//log_e("Ack Error! Addr: %x", address >> 1);
144+
return 1;
145+
}
146+
127147
if(i2c->dev->ctr.trans_start || i2c->dev->status_reg.bus_busy || !(i2c->dev->int_raw.trans_complete) || !(i2c->dev->command[2].done)) {
128148
continue;
129-
} else if(i2c->dev->int_raw.ack_err || i2c->dev->int_raw.time_out || i2c->dev->int_raw.arbitration_lost) {
130-
break;
131149
} else if(i2c->dev->command[2].done) {
132150
break;
133151
}
134152
}
135153

136-
//Bus failed (maybe check for this while waiting?
137-
if(i2c->dev->int_raw.arbitration_lost) {
138-
//log_e("Bus Fail! Addr: %x", address >> 1);
139-
return 4;
140-
}
141-
142-
//Bus timeout
143-
if(i2c->dev->int_raw.time_out) {
144-
//log_e("Bus Timeout! Addr: %x", address >> 1);
145-
return 3;
146-
}
147-
148-
//Transmission did not finish and ACK_ERR is set
149-
if(i2c->dev->int_raw.ack_err) {
150-
//log_e("Ack Error! Addr: %x", address >> 1);
151-
return 1;
152-
}
153-
154154
}
155155
return 0;
156156
}
@@ -163,6 +163,8 @@ int i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint
163163
uint8_t cmdIdx;
164164
uint8_t willRead;
165165

166+
i2cResetFiFo(i2c);
167+
166168
//CMD START
167169
i2cSetCmd(i2c, 0, I2C_CMD_RSTART, 0, false, false, false);
168170

@@ -176,6 +178,10 @@ int i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint
176178
while(len) {
177179
cmdIdx = (index)?0:2;
178180
willRead = (len > 32)?32:(len-1);
181+
if(cmdIdx){
182+
i2cResetFiFo(i2c);
183+
}
184+
179185
i2cSetCmd(i2c, cmdIdx++, I2C_CMD_READ, willRead, false, false, false);
180186
if((len - willRead) > 1) {
181187
i2cSetCmd(i2c, cmdIdx++, I2C_CMD_END, 0, false, false, false);
@@ -195,32 +201,30 @@ int i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint
195201

196202
//WAIT Transmission
197203
while(1) {
204+
//Bus failed (maybe check for this while waiting?
205+
if(i2c->dev->int_raw.arbitration_lost) {
206+
//log_e("Bus Fail! Addr: %x", address >> 1);
207+
return -4;
208+
}
209+
210+
//Bus timeout
211+
if(i2c->dev->int_raw.time_out) {
212+
//log_e("Bus Timeout! Addr: %x", address >> 1);
213+
return -3;
214+
}
215+
216+
//Transmission did not finish and ACK_ERR is set
217+
if(i2c->dev->int_raw.ack_err) {
218+
//log_e("Ack Error! Addr: %x", address >> 1);
219+
return -1;
220+
}
198221
if(i2c->dev->ctr.trans_start || i2c->dev->status_reg.bus_busy || !(i2c->dev->int_raw.trans_complete) || !(i2c->dev->command[cmdIdx-1].done)) {
199222
continue;
200-
} else if(i2c->dev->int_raw.ack_err || i2c->dev->int_raw.time_out || i2c->dev->int_raw.arbitration_lost) {
201-
break;
202223
} else if(i2c->dev->command[cmdIdx-1].done) {
203224
break;
204225
}
205226
}
206227

207-
//Bus failed (maybe check for this while waiting?
208-
if(i2c->dev->int_raw.arbitration_lost) {
209-
//log_e("Bus Fail! Addr: %x", address >> 1);
210-
return -4;
211-
}
212-
213-
//Bus timeout
214-
if(i2c->dev->int_raw.time_out) {
215-
//log_e("Bus Timeout! Addr: %x", address >> 1);
216-
return -3;
217-
}
218-
219-
//Transmission did not finish and ACK_ERR is set
220-
if(i2c->dev->int_raw.ack_err) {
221-
//log_e("Ack Error! Addr: %x", address >> 1);
222-
return -1;
223-
}
224228
int i = 0;
225229
while(i<willRead) {
226230
i++;

0 commit comments

Comments
 (0)