Skip to content

Navigation Menu

Sign in
Appearance settings

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 0cd6285

Browse filesBrowse files
lonerzzzme-no-dev
authored andcommitted
I2c reset functionality (espressif#678)
* Addition of a i2cReset method and timeout handling for the case where the i2c hardware FSM (state machine) gets stuck in a busy state. * Use newly added i2cReset function within the wire library.
1 parent 10ff1de commit 0cd6285
Copy full SHA for 0cd6285

File tree

Expand file treeCollapse file tree

4 files changed

+47
-3
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

4 files changed

+47
-3
lines changed
Open diff view settings
Collapse file

‎cores/esp32/esp32-hal-i2c.c‎

Copy file name to clipboardExpand all lines: cores/esp32/esp32-hal-i2c.c
+35-2Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "freertos/task.h"
1919
#include "freertos/semphr.h"
2020
#include "rom/ets_sys.h"
21+
#include "driver/periph_ctrl.h"
2122
#include "soc/i2c_reg.h"
2223
#include "soc/i2c_struct.h"
2324
#include "soc/dport_reg.h"
@@ -154,6 +155,13 @@ i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * dat
154155

155156
I2C_MUTEX_LOCK();
156157

158+
if (i2c->dev->status_reg.bus_busy == 1)
159+
{
160+
//log_w( "Busy Timeout! Addr: %x", address >> 1 );
161+
I2C_MUTEX_UNLOCK();
162+
return I2C_ERROR_BUSY;
163+
}
164+
157165
while(dataLen) {
158166
uint8_t willSend = (dataLen > 32)?32:dataLen;
159167
uint8_t dataSend = willSend;
@@ -221,7 +229,7 @@ i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * dat
221229
//Transmission did not finish and ACK_ERR is set
222230
if(i2c->dev->int_raw.ack_err) {
223231
//log_w("Ack Error! Addr: %x", address >> 1);
224-
while(i2c->dev->status_reg.bus_busy);
232+
while((i2c->dev->status_reg.bus_busy) && ((millis() - startAt)>50));
225233
I2C_MUTEX_UNLOCK();
226234
return I2C_ERROR_ACK;
227235
}
@@ -250,6 +258,13 @@ i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data
250258

251259
I2C_MUTEX_LOCK();
252260

261+
if (i2c->dev->status_reg.bus_busy == 1)
262+
{
263+
//log_w( "Busy Timeout! Addr: %x", address >> 1 );
264+
I2C_MUTEX_UNLOCK();
265+
return I2C_ERROR_BUSY;
266+
}
267+
253268
i2cResetFiFo(i2c);
254269
i2cResetCmd(i2c);
255270

@@ -445,7 +460,25 @@ void i2cInitFix(i2c_t * i2c){
445460
i2c->dev->fifo_data.data = 0;
446461
i2cSetCmd(i2c, 1, I2C_CMD_WRITE, 1, false, false, false);
447462
i2cSetCmd(i2c, 2, I2C_CMD_STOP, 0, false, false, false);
463+
if (i2c->dev->status_reg.bus_busy) // If this condition is true, the while loop will timeout as done will not be set
464+
{
465+
//log_e("Busy at initialization!");
466+
}
448467
i2c->dev->ctr.trans_start = 1;
449-
while(!i2c->dev->command[2].done);
468+
uint16_t count = 50000;
469+
while ((!i2c->dev->command[2].done) && (--count > 0));
450470
I2C_MUTEX_UNLOCK();
451471
}
472+
473+
void i2cReset(i2c_t* i2c){
474+
if(i2c == NULL){
475+
return;
476+
}
477+
I2C_MUTEX_LOCK();
478+
periph_module_t moduleId = (i2c == &_i2c_bus_array[0])?PERIPH_I2C0_MODULE:PERIPH_I2C1_MODULE;
479+
periph_module_disable( moduleId );
480+
delay( 20 ); // Seems long but delay was chosen to ensure system teardown and setup without core generation
481+
periph_module_enable( moduleId );
482+
I2C_MUTEX_UNLOCK();
483+
}
484+
Collapse file

‎cores/esp32/esp32-hal-i2c.h‎

Copy file name to clipboardExpand all lines: cores/esp32/esp32-hal-i2c.h
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ typedef enum {
2727
I2C_ERROR_DEV,
2828
I2C_ERROR_ACK,
2929
I2C_ERROR_TIMEOUT,
30-
I2C_ERROR_BUS
30+
I2C_ERROR_BUS,
31+
I2C_ERROR_BUSY
3132
} i2c_err_t;
3233

3334
struct i2c_struct_t;
@@ -50,6 +51,7 @@ i2c_err_t i2cDetachSDA(i2c_t * i2c, int8_t sda);
5051
i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint8_t len, bool sendStop);
5152
i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint8_t len, bool sendStop);
5253

54+
void i2cReset(i2c_t* i2c);
5355

5456
#ifdef __cplusplus
5557
}
Collapse file

‎libraries/Wire/src/Wire.cpp‎

Copy file name to clipboardExpand all lines: libraries/Wire/src/Wire.cpp
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,4 +211,11 @@ void TwoWire::flush(void)
211211
txLength = 0;
212212
}
213213

214+
void TwoWire::reset(void)
215+
{
216+
i2cReset( i2c );
217+
i2c = NULL;
218+
begin( sda, scl );
219+
}
220+
214221
TwoWire Wire = TwoWire(0);
Collapse file

‎libraries/Wire/src/Wire.h‎

Copy file name to clipboardExpand all lines: libraries/Wire/src/Wire.h
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ class TwoWire: public Stream
7272
int peek(void);
7373
void flush(void);
7474

75+
void reset(void);
76+
7577
inline size_t write(const char * s)
7678
{
7779
return write((uint8_t*) s, strlen(s));

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.