Merge pull request #751 from espressif/longReads
Add initial handling for long I2C reads.
This commit is contained in:
commit
2a1a62a90a
@ -31,6 +31,8 @@
|
|||||||
#define DR_REG_I2C_EXT_BASE_FIXED 0x60013000
|
#define DR_REG_I2C_EXT_BASE_FIXED 0x60013000
|
||||||
#define DR_REG_I2C1_EXT_BASE_FIXED 0x60027000
|
#define DR_REG_I2C1_EXT_BASE_FIXED 0x60027000
|
||||||
|
|
||||||
|
#define COMMAND_BUFFER_LENGTH 16
|
||||||
|
|
||||||
struct i2c_struct_t {
|
struct i2c_struct_t {
|
||||||
i2c_dev_t * dev;
|
i2c_dev_t * dev;
|
||||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||||
@ -127,26 +129,25 @@ void i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uint8_t byte_num, bo
|
|||||||
i2c->dev->command[index].op_code = op_code;
|
i2c->dev->command[index].op_code = op_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void i2cResetCmd(i2c_t * i2c){
|
void i2cResetCmd(i2c_t * i2c) {
|
||||||
int i;
|
uint8_t i;
|
||||||
for(i=0;i<16;i++){
|
for(i=0;i<16;i++){
|
||||||
i2c->dev->command[i].val = 0;
|
i2c->dev->command[i].val = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void i2cResetFiFo(i2c_t * i2c)
|
void i2cResetFiFo(i2c_t * i2c) {
|
||||||
{
|
|
||||||
i2c->dev->fifo_conf.tx_fifo_rst = 1;
|
i2c->dev->fifo_conf.tx_fifo_rst = 1;
|
||||||
i2c->dev->fifo_conf.tx_fifo_rst = 0;
|
i2c->dev->fifo_conf.tx_fifo_rst = 0;
|
||||||
i2c->dev->fifo_conf.rx_fifo_rst = 1;
|
i2c->dev->fifo_conf.rx_fifo_rst = 1;
|
||||||
i2c->dev->fifo_conf.rx_fifo_rst = 0;
|
i2c->dev->fifo_conf.rx_fifo_rst = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint8_t len, bool sendStop)
|
i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint16_t len, bool sendStop)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint8_t index = 0;
|
uint16_t index = 0;
|
||||||
uint8_t dataLen = len + (addr_10bit?2:1);
|
uint16_t dataLen = len + (addr_10bit?2:1);
|
||||||
address = (address << 1);
|
address = (address << 1);
|
||||||
|
|
||||||
if(i2c == NULL){
|
if(i2c == NULL){
|
||||||
@ -244,12 +245,25 @@ i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * dat
|
|||||||
return I2C_ERROR_OK;
|
return I2C_ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint8_t len, bool sendStop)
|
uint8_t inc( uint8_t* index )
|
||||||
|
{
|
||||||
|
uint8_t i = index[ 0 ];
|
||||||
|
if (++index[ 0 ] == COMMAND_BUFFER_LENGTH)
|
||||||
|
{
|
||||||
|
index[ 0 ] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint16_t len, bool sendStop)
|
||||||
{
|
{
|
||||||
address = (address << 1) | 1;
|
address = (address << 1) | 1;
|
||||||
uint8_t addrLen = (addr_10bit?2:1);
|
uint8_t addrLen = (addr_10bit?2:1);
|
||||||
uint8_t index = 0;
|
uint8_t amountRead[16];
|
||||||
uint8_t cmdIdx;
|
uint16_t index = 0;
|
||||||
|
uint8_t cmdIdx = 0, currentCmdIdx = 0, nextCmdCount;
|
||||||
|
bool stopped = false, isEndNear = false;
|
||||||
uint8_t willRead;
|
uint8_t willRead;
|
||||||
|
|
||||||
if(i2c == NULL){
|
if(i2c == NULL){
|
||||||
@ -269,62 +283,42 @@ i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data
|
|||||||
i2cResetCmd(i2c);
|
i2cResetCmd(i2c);
|
||||||
|
|
||||||
//CMD START
|
//CMD START
|
||||||
i2cSetCmd(i2c, 0, I2C_CMD_RSTART, 0, false, false, false);
|
i2cSetCmd(i2c, cmdIdx++, I2C_CMD_RSTART, 0, false, false, false);
|
||||||
|
|
||||||
//CMD WRITE ADDRESS
|
//CMD WRITE ADDRESS
|
||||||
i2c->dev->fifo_data.val = address & 0xFF;
|
i2c->dev->fifo_data.val = address & 0xFF;
|
||||||
if(addr_10bit) {
|
if(addr_10bit) {
|
||||||
i2c->dev->fifo_data.val = (address >> 8) & 0xFF;
|
i2c->dev->fifo_data.val = (address >> 8) & 0xFF;
|
||||||
}
|
}
|
||||||
i2cSetCmd(i2c, 1, I2C_CMD_WRITE, addrLen, false, false, true);
|
i2cSetCmd(i2c, cmdIdx++, I2C_CMD_WRITE, addrLen, false, false, true);
|
||||||
|
nextCmdCount = cmdIdx;
|
||||||
|
|
||||||
while(len) {
|
//Clear Interrupts
|
||||||
cmdIdx = (index)?0:2;
|
i2c->dev->int_clr.val = 0x00001FFF;
|
||||||
willRead = (len > 32)?32:(len-1);
|
|
||||||
if(cmdIdx){
|
|
||||||
i2cResetFiFo(i2c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(willRead){
|
|
||||||
i2cSetCmd(i2c, cmdIdx++, I2C_CMD_READ, willRead, false, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if((len - willRead) > 1) {
|
|
||||||
i2cSetCmd(i2c, cmdIdx++, I2C_CMD_END, 0, false, false, false);
|
|
||||||
} else {
|
|
||||||
willRead++;
|
|
||||||
i2cSetCmd(i2c, cmdIdx++, I2C_CMD_READ, 1, true, false, false);
|
|
||||||
if(sendStop) {
|
|
||||||
i2cSetCmd(i2c, cmdIdx++, I2C_CMD_STOP, 0, false, false, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Clear Interrupts
|
|
||||||
i2c->dev->int_clr.val = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
//START Transmission
|
|
||||||
i2c->dev->ctr.trans_start = 1;
|
|
||||||
|
|
||||||
|
//START Transmission
|
||||||
|
i2c->dev->ctr.trans_start = 1;
|
||||||
|
while (!stopped) {
|
||||||
//WAIT Transmission
|
//WAIT Transmission
|
||||||
uint32_t startAt = millis();
|
uint32_t startAt = millis();
|
||||||
while(1) {
|
while(1) {
|
||||||
//have been looping for too long
|
//have been looping for too long
|
||||||
if((millis() - startAt)>50){
|
if((millis() - startAt)>50) {
|
||||||
log_e("Timeout! Addr: %x", address >> 1);
|
log_e("Timeout! Addr: %x, index %d", (address >> 1), index);
|
||||||
I2C_MUTEX_UNLOCK();
|
I2C_MUTEX_UNLOCK();
|
||||||
return I2C_ERROR_BUS;
|
return I2C_ERROR_BUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Bus failed (maybe check for this while waiting?
|
//Bus failed (maybe check for this while waiting?
|
||||||
if(i2c->dev->int_raw.arbitration_lost) {
|
if(i2c->dev->int_raw.arbitration_lost) {
|
||||||
log_e("Bus Fail! Addr: %x", address >> 1);
|
log_e("Bus Fail! Addr: %x", (address >> 1));
|
||||||
I2C_MUTEX_UNLOCK();
|
I2C_MUTEX_UNLOCK();
|
||||||
return I2C_ERROR_BUS;
|
return I2C_ERROR_BUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Bus timeout
|
//Bus timeout
|
||||||
if(i2c->dev->int_raw.time_out) {
|
if(i2c->dev->int_raw.time_out) {
|
||||||
log_e("Bus Timeout! Addr: %x", address >> 1);
|
log_e("Bus Timeout! Addr: %x, index %d", (address >> 1), index );
|
||||||
I2C_MUTEX_UNLOCK();
|
I2C_MUTEX_UNLOCK();
|
||||||
return I2C_ERROR_TIMEOUT;
|
return I2C_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
@ -332,23 +326,47 @@ i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data
|
|||||||
//Transmission did not finish and ACK_ERR is set
|
//Transmission did not finish and ACK_ERR is set
|
||||||
if(i2c->dev->int_raw.ack_err) {
|
if(i2c->dev->int_raw.ack_err) {
|
||||||
log_w("Ack Error! Addr: %x", address >> 1);
|
log_w("Ack Error! Addr: %x", address >> 1);
|
||||||
|
while((i2c->dev->status_reg.bus_busy) && ((millis() - startAt)<50));
|
||||||
I2C_MUTEX_UNLOCK();
|
I2C_MUTEX_UNLOCK();
|
||||||
return I2C_ERROR_ACK;
|
return I2C_ERROR_ACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i2c->dev->command[cmdIdx-1].done) {
|
// Save bytes from the buffer as they arrive instead of doing them at the end of the loop since there is no
|
||||||
|
// pause from an END operation in this approach.
|
||||||
|
if((!isEndNear) && (nextCmdCount < 2)) {
|
||||||
|
if (willRead = ((len>32)?32:len)) {
|
||||||
|
if (willRead > 1) {
|
||||||
|
i2cSetCmd(i2c, cmdIdx, I2C_CMD_READ, (amountRead[ inc( &cmdIdx ) ] = willRead -1), false, false, false);
|
||||||
|
nextCmdCount++;
|
||||||
|
}
|
||||||
|
i2cSetCmd(i2c, cmdIdx, I2C_CMD_READ, (amountRead[ inc( &cmdIdx ) ] = 1), (len<=32), false, false);
|
||||||
|
nextCmdCount++;
|
||||||
|
len -= willRead;
|
||||||
|
} else {
|
||||||
|
i2cSetCmd(i2c, inc( &cmdIdx ), I2C_CMD_STOP, 0, false, false, false);
|
||||||
|
isEndNear = true;
|
||||||
|
nextCmdCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i2c->dev->command[currentCmdIdx].done) {
|
||||||
|
nextCmdCount--;
|
||||||
|
if (i2c->dev->command[currentCmdIdx].op_code == I2C_CMD_READ) {
|
||||||
|
while(amountRead[currentCmdIdx]>0) {
|
||||||
|
data[index++] = i2c->dev->fifo_data.val & 0xFF;
|
||||||
|
amountRead[currentCmdIdx]--;
|
||||||
|
}
|
||||||
|
i2cResetFiFo(i2c);
|
||||||
|
} else if (i2c->dev->command[currentCmdIdx].op_code == I2C_CMD_STOP) {
|
||||||
|
stopped = true;
|
||||||
|
}
|
||||||
|
inc( ¤tCmdIdx );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
while(i<willRead) {
|
|
||||||
i++;
|
|
||||||
data[index++] = i2c->dev->fifo_data.val & 0xFF;
|
|
||||||
}
|
|
||||||
len -= willRead;
|
|
||||||
}
|
}
|
||||||
I2C_MUTEX_UNLOCK();
|
I2C_MUTEX_UNLOCK();
|
||||||
|
|
||||||
return I2C_ERROR_OK;
|
return I2C_ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +452,7 @@ i2c_t * i2cInit(uint8_t i2c_num, uint16_t slave_addr, bool addr_10bit_en)
|
|||||||
i2c->dev->ctr.clk_en = 1;
|
i2c->dev->ctr.clk_en = 1;
|
||||||
|
|
||||||
//the max clock number of receiving a data
|
//the max clock number of receiving a data
|
||||||
i2c->dev->timeout.tout = 400000;//clocks max=1048575
|
i2c->dev->timeout.tout = 1048575;//clocks max=1048575
|
||||||
//disable apb nonfifo access
|
//disable apb nonfifo access
|
||||||
i2c->dev->fifo_conf.nonfifo_en = 0;
|
i2c->dev->fifo_conf.nonfifo_en = 0;
|
||||||
|
|
||||||
|
@ -48,8 +48,8 @@ i2c_err_t i2cDetachSCL(i2c_t * i2c, int8_t scl);
|
|||||||
i2c_err_t i2cAttachSDA(i2c_t * i2c, int8_t sda);
|
i2c_err_t i2cAttachSDA(i2c_t * i2c, int8_t sda);
|
||||||
i2c_err_t i2cDetachSDA(i2c_t * i2c, int8_t sda);
|
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 i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint16_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);
|
i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint16_t len, bool sendStop);
|
||||||
|
|
||||||
void i2cReset(i2c_t* i2c);
|
void i2cReset(i2c_t* i2c);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user