提交 0cd62852 编写于 作者: J Jason K 提交者: Me No Dev

I2c reset functionality (#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.
上级 10ff1def
......@@ -18,6 +18,7 @@
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "rom/ets_sys.h"
#include "driver/periph_ctrl.h"
#include "soc/i2c_reg.h"
#include "soc/i2c_struct.h"
#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
I2C_MUTEX_LOCK();
if (i2c->dev->status_reg.bus_busy == 1)
{
//log_w( "Busy Timeout! Addr: %x", address >> 1 );
I2C_MUTEX_UNLOCK();
return I2C_ERROR_BUSY;
}
while(dataLen) {
uint8_t willSend = (dataLen > 32)?32:dataLen;
uint8_t dataSend = willSend;
......@@ -221,7 +229,7 @@ i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * dat
//Transmission did not finish and ACK_ERR is set
if(i2c->dev->int_raw.ack_err) {
//log_w("Ack Error! Addr: %x", address >> 1);
while(i2c->dev->status_reg.bus_busy);
while((i2c->dev->status_reg.bus_busy) && ((millis() - startAt)>50));
I2C_MUTEX_UNLOCK();
return I2C_ERROR_ACK;
}
......@@ -250,6 +258,13 @@ i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data
I2C_MUTEX_LOCK();
if (i2c->dev->status_reg.bus_busy == 1)
{
//log_w( "Busy Timeout! Addr: %x", address >> 1 );
I2C_MUTEX_UNLOCK();
return I2C_ERROR_BUSY;
}
i2cResetFiFo(i2c);
i2cResetCmd(i2c);
......@@ -445,7 +460,25 @@ void i2cInitFix(i2c_t * i2c){
i2c->dev->fifo_data.data = 0;
i2cSetCmd(i2c, 1, I2C_CMD_WRITE, 1, false, false, false);
i2cSetCmd(i2c, 2, I2C_CMD_STOP, 0, false, false, false);
if (i2c->dev->status_reg.bus_busy) // If this condition is true, the while loop will timeout as done will not be set
{
//log_e("Busy at initialization!");
}
i2c->dev->ctr.trans_start = 1;
while(!i2c->dev->command[2].done);
uint16_t count = 50000;
while ((!i2c->dev->command[2].done) && (--count > 0));
I2C_MUTEX_UNLOCK();
}
void i2cReset(i2c_t* i2c){
if(i2c == NULL){
return;
}
I2C_MUTEX_LOCK();
periph_module_t moduleId = (i2c == &_i2c_bus_array[0])?PERIPH_I2C0_MODULE:PERIPH_I2C1_MODULE;
periph_module_disable( moduleId );
delay( 20 ); // Seems long but delay was chosen to ensure system teardown and setup without core generation
periph_module_enable( moduleId );
I2C_MUTEX_UNLOCK();
}
......@@ -27,7 +27,8 @@ typedef enum {
I2C_ERROR_DEV,
I2C_ERROR_ACK,
I2C_ERROR_TIMEOUT,
I2C_ERROR_BUS
I2C_ERROR_BUS,
I2C_ERROR_BUSY
} i2c_err_t;
struct i2c_struct_t;
......@@ -50,6 +51,7 @@ i2c_err_t i2cDetachSDA(i2c_t * i2c, int8_t sda);
i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint8_t len, bool sendStop);
i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint8_t len, bool sendStop);
void i2cReset(i2c_t* i2c);
#ifdef __cplusplus
}
......
......@@ -211,4 +211,11 @@ void TwoWire::flush(void)
txLength = 0;
}
void TwoWire::reset(void)
{
i2cReset( i2c );
i2c = NULL;
begin( sda, scl );
}
TwoWire Wire = TwoWire(0);
......@@ -72,6 +72,8 @@ public:
int peek(void);
void flush(void);
void reset(void);
inline size_t write(const char * s)
{
return write((uint8_t*) s, strlen(s));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册