Skip to content

Commit c19fc06

Browse files
committed
Hopefully fix I2C/Wire
Tested with (all at the same time): - MPU9250 - HTU21 - TMP102 - BMP180 - AM2320 - SSD1306
1 parent e92634a commit c19fc06

File tree

3 files changed

+71
-25
lines changed

3 files changed

+71
-25
lines changed

cores/esp32/esp32-hal-i2c.c

+65-25
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * dat
158158

159159
i2cResetFiFo(i2c);
160160
i2cResetCmd(i2c);
161+
//Clear Interrupts
162+
i2c->dev->int_clr.val = 0xFFFFFFFF;
161163

162164
//CMD START
163165
i2cSetCmd(i2c, 0, I2C_CMD_RSTART, 0, false, false, false);
@@ -174,26 +176,32 @@ i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * dat
174176
i = 0;
175177
while(i<dataSend) {
176178
i++;
177-
i2c->dev->fifo_data.data = data[index++];
179+
i2c->dev->fifo_data.val = data[index++];
180+
while(i2c->dev->status_reg.tx_fifo_cnt < i);
178181
}
179182
i2cSetCmd(i2c, 1, I2C_CMD_WRITE, willSend, false, false, true);
180183
dataLen -= willSend;
181184

182185
//CMD STOP or CMD END if there is more data
183-
if(dataLen) {
186+
if(dataLen || !sendStop) {
184187
i2cSetCmd(i2c, 2, I2C_CMD_END, 0, false, false, false);
185188
} else if(sendStop) {
186189
i2cSetCmd(i2c, 2, I2C_CMD_STOP, 0, false, false, false);
187190
}
188191

189-
//Clear Interrupts
190-
i2c->dev->int_clr.val = 0xFFFFFFFF;
191-
192192
//START Transmission
193193
i2c->dev->ctr.trans_start = 1;
194194

195195
//WAIT Transmission
196+
uint32_t startAt = millis();
196197
while(1) {
198+
//have been looping for too long
199+
if((millis() - startAt)>50){
200+
//log_e("Timeout! Addr: %x", address >> 1);
201+
I2C_MUTEX_UNLOCK();
202+
return I2C_ERROR_BUS;
203+
}
204+
197205
//Bus failed (maybe check for this while waiting?
198206
if(i2c->dev->int_raw.arbitration_lost) {
199207
//log_e("Bus Fail! Addr: %x", address >> 1);
@@ -210,14 +218,12 @@ i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * dat
210218

211219
//Transmission did not finish and ACK_ERR is set
212220
if(i2c->dev->int_raw.ack_err) {
213-
//log_e("Ack Error! Addr: %x", address >> 1);
221+
//log_w("Ack Error! Addr: %x", address >> 1);
214222
I2C_MUTEX_UNLOCK();
215223
return I2C_ERROR_ACK;
216224
}
217225

218-
if(i2c->dev->ctr.trans_start || i2c->dev->status_reg.bus_busy || !(i2c->dev->int_raw.trans_complete) || !(i2c->dev->command[2].done)) {
219-
continue;
220-
} else if(i2c->dev->command[2].done) {
226+
if((sendStop && i2c->dev->command[2].done) || !i2c->dev->status_reg.bus_busy){
221227
break;
222228
}
223229
}
@@ -248,9 +254,9 @@ i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data
248254
i2cSetCmd(i2c, 0, I2C_CMD_RSTART, 0, false, false, false);
249255

250256
//CMD WRITE ADDRESS
251-
i2c->dev->fifo_data.data = address & 0xFF;
257+
i2c->dev->fifo_data.val = address & 0xFF;
252258
if(addr_10bit) {
253-
i2c->dev->fifo_data.data = (address >> 8) & 0xFF;
259+
i2c->dev->fifo_data.val = (address >> 8) & 0xFF;
254260
}
255261
i2cSetCmd(i2c, 1, I2C_CMD_WRITE, addrLen, false, false, true);
256262

@@ -279,7 +285,15 @@ i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data
279285
i2c->dev->ctr.trans_start = 1;
280286

281287
//WAIT Transmission
288+
uint32_t startAt = millis();
282289
while(1) {
290+
//have been looping for too long
291+
if((millis() - startAt)>50){
292+
//log_e("Timeout! Addr: %x", address >> 1);
293+
I2C_MUTEX_UNLOCK();
294+
return I2C_ERROR_BUS;
295+
}
296+
283297
//Bus failed (maybe check for this while waiting?
284298
if(i2c->dev->int_raw.arbitration_lost) {
285299
//log_e("Bus Fail! Addr: %x", address >> 1);
@@ -296,21 +310,20 @@ i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data
296310

297311
//Transmission did not finish and ACK_ERR is set
298312
if(i2c->dev->int_raw.ack_err) {
299-
//log_e("Ack Error! Addr: %x", address >> 1);
313+
//log_w("Ack Error! Addr: %x", address >> 1);
300314
I2C_MUTEX_UNLOCK();
301315
return I2C_ERROR_ACK;
302316
}
303-
if(i2c->dev->ctr.trans_start || i2c->dev->status_reg.bus_busy || !(i2c->dev->int_raw.trans_complete) || !(i2c->dev->command[cmdIdx-1].done)) {
304-
continue;
305-
} else if(i2c->dev->command[cmdIdx-1].done) {
317+
318+
if(i2c->dev->command[cmdIdx-1].done) {
306319
break;
307320
}
308321
}
309322

310323
int i = 0;
311324
while(i<willRead) {
312325
i++;
313-
data[index++] = i2c->dev->fifo_data.data;
326+
data[index++] = i2c->dev->fifo_data.val & 0xFF;
314327
}
315328
len -= willRead;
316329
}
@@ -320,24 +333,34 @@ i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data
320333

321334
i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed)
322335
{
323-
uint32_t period = (APB_CLK_FREQ/clk_speed) / 2;
324-
325336
if(i2c == NULL){
326337
return I2C_ERROR_DEV;
327338
}
328339

340+
uint32_t period = (APB_CLK_FREQ/clk_speed) / 2;
341+
uint32_t halfPeriod = period/2;
342+
uint32_t quarterPeriod = period/4;
343+
329344
I2C_MUTEX_LOCK();
345+
//the clock num during SCL is low level
330346
i2c->dev->scl_low_period.scl_low_period = period;
347+
//the clock num during SCL is high level
331348
i2c->dev->scl_high_period.period = period;
332349

333-
i2c->dev->scl_start_hold.time = 50;
334-
i2c->dev->scl_rstart_setup.time = 50;
350+
//the clock num between the negedge of SDA and negedge of SCL for start mark
351+
i2c->dev->scl_start_hold.time = halfPeriod;
352+
//the clock num between the posedge of SCL and the negedge of SDA for restart mark
353+
i2c->dev->scl_rstart_setup.time = halfPeriod;
335354

336-
i2c->dev->scl_stop_hold.time = 50;
337-
i2c->dev->scl_stop_setup.time = 50;
355+
//the clock num after the STOP bit's posedge
356+
i2c->dev->scl_stop_hold.time = halfPeriod;
357+
//the clock num between the posedge of SCL and the posedge of SDA
358+
i2c->dev->scl_stop_setup.time = halfPeriod;
338359

339-
i2c->dev->sda_hold.time = 25;
340-
i2c->dev->sda_sample.time = 25;
360+
//the clock num I2C used to hold the data after the negedge of SCL.
361+
i2c->dev->sda_hold.time = quarterPeriod;
362+
//the clock num I2C used to sample data on SDA after the posedge of SCL
363+
i2c->dev->sda_sample.time = quarterPeriod;
341364
I2C_MUTEX_UNLOCK();
342365
return I2C_ERROR_OK;
343366
}
@@ -389,7 +412,9 @@ i2c_t * i2cInit(uint8_t i2c_num, uint16_t slave_addr, bool addr_10bit_en)
389412
i2c->dev->ctr.scl_force_out = 1 ;
390413
i2c->dev->ctr.clk_en = 1;
391414

415+
//the max clock number of receiving a data
392416
i2c->dev->timeout.tout = 400000;//clocks max=1048575
417+
//disable apb nonfifo access
393418
i2c->dev->fifo_conf.nonfifo_en = 0;
394419

395420
i2c->dev->slave_addr.val = 0;
@@ -402,4 +427,19 @@ i2c_t * i2cInit(uint8_t i2c_num, uint16_t slave_addr, bool addr_10bit_en)
402427
return i2c;
403428
}
404429

405-
430+
void i2cInitFix(i2c_t * i2c){
431+
if(i2c == NULL){
432+
return;
433+
}
434+
I2C_MUTEX_LOCK();
435+
i2cResetFiFo(i2c);
436+
i2cResetCmd(i2c);
437+
i2c->dev->int_clr.val = 0xFFFFFFFF;
438+
i2cSetCmd(i2c, 0, I2C_CMD_RSTART, 0, false, false, false);
439+
i2c->dev->fifo_data.data = 0;
440+
i2cSetCmd(i2c, 1, I2C_CMD_WRITE, 1, false, false, false);
441+
i2cSetCmd(i2c, 2, I2C_CMD_STOP, 0, false, false, false);
442+
i2c->dev->ctr.trans_start = 1;
443+
while(!i2c->dev->command[2].done);
444+
I2C_MUTEX_UNLOCK();
445+
}

cores/esp32/esp32-hal-i2c.h

+4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ typedef struct i2c_struct_t i2c_t;
3535

3636
i2c_t * i2cInit(uint8_t i2c_num, uint16_t slave_addr, bool addr_10bit_en);
3737

38+
//call this after you setup the bus and pins to send empty packet
39+
//required because when pins are attached, they emit pulses that lock the bus
40+
void i2cInitFix(i2c_t * i2c);
41+
3842
i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed);
3943
uint32_t i2cGetFrequency(i2c_t * i2c);
4044

libraries/Wire/src/Wire.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ void TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
8686
i2cAttachSCL(i2c, scl);
8787

8888
flush();
89+
90+
i2cInitFix(i2c);
8991
}
9092

9193
void TwoWire::setClock(uint32_t frequency)

0 commit comments

Comments
 (0)