LPC open I2C driver - I2C master state machine

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC open I2C driver - I2C master state machine

1,186 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gnxp on Tue Sep 23 04:41:43 MST 2014
Environment - lpc xpresso 1769 board with 24LC64 EEPROM on I2C, lpc open 2.10 library

Going through I2C driver and the documentation, I find a discrepancy. The below code is directly from lpc driver with two commented lines which I added for the following explained reason.

/* Master transfer state change handler handler */
int handleMasterXferState(LPC_I2C_T *pI2C, I2C_XFER_T  *xfer)
{
uint32_t cclr = I2C_CON_FLAGS;

switch (getCurState(pI2C)) {
case 0x08:/* Start condition on bus */
case 0x10:/* Repeated start condition */
pI2C->DAT = (xfer->slaveAddr << 1) | (xfer->txSz == 0);
//cclr &= ~I2C_CON_AA; /* Set AA bit??? */
break;

/* Tx handling */
case 0x18:/* SLA+W sent and ACK received */
case 0x28:/* DATA sent and ACK received */
if (!xfer->txSz) {
cclr &= ~(xfer->rxSz ? I2C_CON_STA : I2C_CON_STO);
}
else {
pI2C->DAT = *xfer->txBuff++;
xfer->txSz--;
//cclr &= ~I2C_CON_AA; /* Set AA bit??? */
}
break;

/* Rx handling */
case 0x58:/* Data Received and NACK sent */
cclr &= ~I2C_CON_STO;

case 0x50:/* Data Received and ACK sent */
*xfer->rxBuff++ = pI2C->DAT;
xfer->rxSz--;

case 0x40:/* SLA+R sent and ACK received */
if (xfer->rxSz > 1) {
cclr &= ~I2C_CON_AA;
}
break;

/* NAK Handling */
case 0x20:/* SLA+W sent NAK received */
case 0x30:/* DATA sent NAK received */
case 0x48:/* SLA+R sent NAK received */
xfer->status = I2C_STATUS_NAK;
cclr &= ~I2C_CON_STO;
break;

case 0x38:/* Arbitration lost */
xfer->status = I2C_STATUS_ARBLOST;
break;

/* Bus Error */
case 0x00:
xfer->status = I2C_STATUS_BUSERR;
cclr &= ~I2C_CON_STO;
}

/* Set clear control flags */
pI2C->CONSET = cclr ^ I2C_CON_FLAGS;
pI2C->CONCLR = cclr;

/* If stopped return 0 */
if (!(cclr & I2C_CON_STO) || (xfer->status == I2C_STATUS_ARBLOST)) {
if (xfer->status == I2C_STATUS_BUSY) {
xfer->status = I2C_STATUS_DONE;
}
return 0;
}
return 1;
}


On rev 3.1 of lpc 1769 user manual(UM10360) pg.476, software handling of I2C states is explained. When 1769 is master and  I2STA reads 0x08,0x10,0x18 or 0x28, AA should be set as explained in pg. 476 and 477. I don't see that in above code. A slave would have to ACK data unless it is physically not able to accept it.

Am I missing understanding anything in code?
Labels (1)
0 Kudos
1 Reply

514 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gnxp on Fri Sep 26 03:05:00 MST 2014
For completion, I'll update this issue.
From Table 399. Master Transmitter mode and table Table 400. Master Receiver mode, it is clear that AA bit is  a don't care in most of situations. Section 19.10 is  a bit misleading. The good news is the driver works really well(at least the master handler which I am concerned about right now). I have managed to read/write data to 24LC64 EEPROM on lpc xpresso board. 32 bytes is the maximum size for a block write. To increase throughput by using ACK polling feature I just added a couple of lines to the driver as shown below.
/* NAK Handling */
case 0x20:/* SLA+W sent NAK received */
/* After a STOP condition, write cycle begins in a EEPROM chip and it  won't ACK during the cycle. We use this to do a ACK polling. This means keep sending START and control byte till you get ACK. Take care to adjust with timeouts as you don't want to be stuck here in case of a dodgy chip  or if chip is full */
xfer->status = I2C_STATUS_BUSY; /* Hold on */
if (xfer->txSz) cclr &= ~I2C_CON_STA;
break;
0 Kudos