8000 Hopefully fix I2C/Wire · eroniki/arduino-esp32@c19fc06 · GitHub
[go: up one dir, main page]

Skip to content

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

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

Lines changed: 65 additions & 25 deletions
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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 2 additions & 0 deletions
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)
0