diff --git a/cores/esp32/esp32-hal-i2c.c b/cores/esp32/esp32-hal-i2c.c index a6b538d8..ffaee693 100644 --- a/cores/esp32/esp32-hal-i2c.c +++ b/cores/esp32/esp32-hal-i2c.c @@ -31,6 +31,8 @@ #define DR_REG_I2C_EXT_BASE_FIXED 0x60013000 #define DR_REG_I2C1_EXT_BASE_FIXED 0x60027000 +#define COMMAND_BUFFER_LENGTH 16 + struct i2c_struct_t { i2c_dev_t * dev; #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; } -void i2cResetCmd(i2c_t * i2c){ - int i; +void i2cResetCmd(i2c_t * i2c) { + uint8_t i; for(i=0;i<16;i++){ 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 = 0; i2c->dev->fifo_conf.rx_fifo_rst = 1; 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; - uint8_t index = 0; - uint8_t dataLen = len + (addr_10bit?2:1); + uint16_t index = 0; + uint16_t dataLen = len + (addr_10bit?2:1); address = (address << 1); 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; } -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; uint8_t addrLen = (addr_10bit?2:1); - uint8_t index = 0; - uint8_t cmdIdx; + uint8_t amountRead[16]; + uint16_t index = 0; + uint8_t cmdIdx = 0, currentCmdIdx = 0, nextCmdCount; + bool stopped = false, isEndNear = false; uint8_t willRead; 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); //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 i2c->dev->fifo_data.val = address & 0xFF; if(addr_10bit) { 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) { - cmdIdx = (index)?0:2; - 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; + //Clear Interrupts + i2c->dev->int_clr.val = 0x00001FFF; + //START Transmission + i2c->dev->ctr.trans_start = 1; + while (!stopped) { //WAIT Transmission uint32_t startAt = millis(); while(1) { //have been looping for too long - if((millis() - startAt)>50){ - log_e("Timeout! Addr: %x", address >> 1); + if((millis() - startAt)>50) { + log_e("Timeout! Addr: %x, index %d", (address >> 1), index); I2C_MUTEX_UNLOCK(); return I2C_ERROR_BUS; } //Bus failed (maybe check for this while waiting? 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(); return I2C_ERROR_BUS; } //Bus timeout 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(); 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 if(i2c->dev->int_raw.ack_err) { log_w("Ack Error! Addr: %x", address >> 1); + while((i2c->dev->status_reg.bus_busy) && ((millis() - startAt)<50)); I2C_MUTEX_UNLOCK(); 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; } } - - int i = 0; - while(idev->fifo_data.val & 0xFF; - } - len -= willRead; } I2C_MUTEX_UNLOCK(); + return I2C_ERROR_OK; } @@ -425,7 +443,7 @@ i2c_t * i2cInit(uint8_t i2c_num, uint16_t slave_addr, bool addr_10bit_en) DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG,DPORT_I2C_EXT1_CLK_EN); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,DPORT_I2C_EXT1_RST); } - + I2C_MUTEX_LOCK(); i2c->dev->ctr.val = 0; i2c->dev->ctr.ms_mode = (slave_addr == 0); @@ -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; //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 i2c->dev->fifo_conf.nonfifo_en = 0; diff --git a/cores/esp32/esp32-hal-i2c.h b/cores/esp32/esp32-hal-i2c.h index 3e988610..f26c7ab2 100644 --- a/cores/esp32/esp32-hal-i2c.h +++ b/cores/esp32/esp32-hal-i2c.h @@ -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 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); +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, uint16_t len, bool sendStop); void i2cReset(i2c_t* i2c);