AnsweredAssumed Answered

fsl_i2c/fsl_i2c_freertos performing partial read

Question asked by Michael Ellis on Feb 23, 2017
Latest reply on Feb 23, 2017 by Michael Ellis

I am trying to implement a PMBUS BlocK Read routine on a KV5 processor using the fsl_i2c_freertos driver.  The I2C sequence for this routine is as follows:

 

1) Master sends START

2) Master sends slave address with lsb cleared (write), slave sends ACK

3) Master sends command byte, slave sends ACK

4) Master sends REPEATED START

5) Master sends slave address with lsb set (read), slave sends ACK

6) Slave sends byte count N, master sends ACK

7) for i = 1 to N-1

7)    Slave sends data(i), master sends ACK

8) Slave sends data(N), master sends NACK

9) Master sends STOP

 

My routine is as follows:

bool psReadBlock(uint8_t cmd, uint8_t *pVal)
{
   ps_data_t *pParms = (ps_data_t *)&ps_data; // get pointer to data
   i2c_master_transfer_t *pXfer = &(pParms->i2c_xfer); // point to transfer structure
   status_t status;
   uint8_t count;

 

   pXfer->direction = kI2C_Write; // send command
   pXfer->data = &cmd;
   pXfer->dataSize = 1;
   pXfer->flags = kI2C_TransferNoStopFlag;
   status = I2C_RTOS_Transfer(&pParms->i2c_handle, pXfer);
   if (status != kStatus_Success)
      return (false);

 

   pXfer->direction = kI2C_Read; // read count value
   pXfer->data = &count;
   pXfer->dataSize = 1;
   pXfer->flags = kI2C_TransferRepeatedStartFlag | kI2C_TransferNoStopFlag;
   status = I2C_RTOS_Transfer(&pParms->i2c_handle, pXfer);
   if (status != kStatus_Success)
      return(false);

 

   pXfer->direction = kI2C_Read; // read data
   pXfer->data = pVal;
   pXfer->dataSize = count;
   pXfer->flags = kI2C_TransferNoStartFlag;
   status = I2C_RTOS_Transfer(&pParms->i2c_handle, pXfer);
   return (status == kStatus_Success);
}

 

The first transaction works as expected but I have a problem with the second transaction.  I set the kI2C_TransferRepeatedStartFlag and kI2C_TransferNoStopFlag.  The REPEATED START is sent (as expected) and no STOP is sent (as expected) but the master sends a NACK instead of an ACK.  This causes the slave device to terminate the sequence and I cannot retrieve the remaining data.

 

I believe that the driver should only send a NACK after reading the final byte of data only if a STOP sequence is to be sent.  if no STOP has been requested then the driver should ACK all bytes being read.

Outcomes