There appears to be a bug in fsl_i2c.c (latest SDK for MCUXpresso for KL17 as of 2018-07-05). I have implemented I2C slave on KL17 and the code works fine in blocking mode but does not work in interrupt driven (specifically, when slave is receiving incoming data. Slave transmit out data works fine). I traced this down to this snipped of code in:
void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
/* Check stop flag. */
if (status & kI2C_StopDetectFlag)
/* Clear the interrupt flag. */
base->S = kI2C_IntPendingFlag;
/* Call slave callback if this is the STOP of the transfer. */
xfer->event = kI2C_SlaveCompletionEvent;
xfer->completionStatus = kStatus_Success;
handle->isBusy = false;
if ((handle->eventMask & xfer->event) && (handle->callback))
handle->callback(base, xfer, handle->userData);
if (!(status & kI2C_AddressMatchFlag))
#endif /* I2C_HAS_STOP_DETECT */
The problem is that when, IRQ is triggered on 'stop' detected, there is still a byte in the data register (data in I2C->D and TFC flag on). However, that byte is never processed because of the last 'if' statement above. I2C->S register does not show 'kI2C_AddressMatchFlag' (IAAS) so the IRQ handler exits and drops last byte. Commenting out that last 'if' statement gets slave receive working using fsl_i2c.c.
This issue is documented in an errata:
I2C: Slave does not hold bus between byte transfers and may result in lost data
When the I2C module is used as a slave device, the bus is not held by the slave between byte transfers. If the I2C slave I2C_D register and the data buffer are full, incoming data from an I2C master will overwrite data in the data buffer.
When configured as a slave, the delay in processing incoming bytes should be minimized. Delay can be minimized by the use of DMA or increased interrupt priority."
I have reported this issue to develop team. The status is in progressing.