Add initial handling for long I2C reads.
This commit is contained in:
		
							parent
							
								
									0c038b4063
								
							
						
					
					
						commit
						1270f40066
					
				| @ -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(i<willRead) { | ||||
|             i++; | ||||
|             data[index++] = i2c->dev->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; | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user