*
* clock : current i2c clock.
* state : global state of the i2c engine.
- * master_status : status returned by i2c block as found in "status" register.
*
* ctrl_buf : This buffer, if used, must have the SAME size as out_buff.
* Then, instead of simply moving to the next byte, the corresponding condition
uint32_t power_bit;
volatile uint32_t clock;
volatile uint32_t state;
- volatile uint32_t master_status;
- volatile uint32_t slave_status;
volatile const char* out_buff;
volatile const char* ctrl_buf;
/* I2C Interrupt handler */
/* Actual version will stop on NACKs */
-/* See LPC1764 user's manual UM10360 on page 457 (19.9.5) for details on I2C State machine */
void I2C_Handler(uint32_t bus_num)
{
- uint8_t status = 0;
uint8_t condition = I2C_CONT;
struct i2c_bus* i2c = &(i2c_buses[bus_num]);
- /* This handler deals with master read and master write only */
- i2c->master_status = i2c->regs->status; /* Store current status */
- i2c->slave_status = i2c->regs->status;
- status = (i2c->regs->status & 0xFF);
-
/* I2C State Machine ! */
- switch (status) {
+ /* This handler deals with master read and master write only */
+ switch (i2c->regs->status & 0xFF) {
/* Errors */
case 0x00: /* Should never happen */
break;
/* NACKs */
- case 0x07: /* NACK on Address */
- case 0x09: /* NACK on Data byte */
+ case 0x06: /* NACK on Address */
+ case 0x07:
+ case 0x08: /* NACK on Data byte */
+ case 0x09:
/* Send a STOP condition will end transactions and let the driver retry later. */
i2c->regs->master_ctrl = I2C_MASTER_STOP;
i2c->state = I2C_NACK;
break;
}
+ /* Done with the Bus, Disable the interrupts */
+ i2c->regs->int_en_clr = (I2C_ST_MASTER_PENDING | I2C_ST_MASTER_ARB_LOSS | I2C_ST_MASTER_STERR);
+ i2c->state = I2C_OK;
+
+ return ret;
+}
+
+/* Release Bus
+ * Some devices do not release the Bus at the end of a transaction if they don't receive
+ * a start condition immediately followed by a stop condition.
+ */
+void i2c_release_bus(uint8_t bus_num)
+{
+ struct i2c_bus* i2c = NULL;
+ if (bus_num >= NB_I2C_BUSSES) {
+ return;
+ }
+ i2c = &(i2c_buses[bus_num]);
/* Force device to release the bus :
- * send a START followed by a STOP (initiate transmission with nul write_length) */
+ * send a START followed by a STOP (initiate transmission with nul write_length) */
i2c->state = I2C_BUSY;
i2c->write_length = 0;
i2c->regs->master_data = 0;
i2c->regs->int_en_set = I2C_ST_MASTER_PENDING;
do {} while (i2c->state == I2C_BUSY); /* FIXME : OS should schedule here */
i2c->state = I2C_OK;
-
+
/* Done with the Bus, Disable the interrupts */
i2c->regs->int_en_clr = (I2C_ST_MASTER_PENDING | I2C_ST_MASTER_ARB_LOSS | I2C_ST_MASTER_STERR);
-
- return ret;
}
/* Read
/***************************************************************************** */
/* Modules I2C access */
/***************************************************************************** */
+
/* I2C Read
* Performs a non-blocking read on the i2c bus.
* cmd_buf : buffer containing all control byte to be sent on the i2c bus
int i2c_write(uint8_t bus_num, const void *buf, size_t count, const void* ctrl_buf);
+/* Release Bus
+ * Some devices do not release the Bus at the end of a transaction if they don't receive
+ * a start condition immediately followed by a stop condition.
+ */
+void i2c_release_bus(uint8_t bus_num);
+
int i2c_set_timeout(uint8_t bus_num, uint16_t timeout);