Hi fellow developers,
I'm reporting on the quality (or rather the lack thereof) of the SDK again. This time it's about the CMSIS I2C driver, see fsl_i2c_cmsis.c. I think that I found another occurrence of the "incomplete implementation pattern".
The ARM CMSIS specification states that a finished I2C transfer is signaled to the application through a callback function. The callback function passes the status as a parameter "event" to the application, see reference driver (scroll to the bottom).
The CMSIS event flags are:
ARM_I2C_EVENT_TRANSFER_DONE | 1UL << 0 | Occurs after Master/Slave Transmit/Receive operation has finished. |
ARM_I2C_EVENT_TRANSFER_INCOMPLETE | 1UL << 1 | Occurs together with ARM_I2C_EVENT_TRANSFER_DONE when less data is transferred then requested. |
ARM_I2C_EVENT_SLAVE_TRANSMIT | 1UL << 2 | Occurs when addressed as Slave Transmitter and ARM_I2C_SlaveTransmit has not been started. |
ARM_I2C_EVENT_SLAVE_RECEIVE | 1UL << 3 | Occurs when addressed as Slave Receiver and ARM_I2C_SlaveReceive has not been started. |
ARM_I2C_EVENT_ADDRESS_NACK | 1UL << 4 | Occurs in master mode when address is not acknowledged from slave. |
ARM_I2C_EVENT_GENERAL_CALL | 1UL << 5 | Indicates General Call in slave mode together with ARM_I2C_EVENT_TRANSFER_DONE, ARM_I2C_EVENT_SLAVE_TRANSMIT and ARM_I2C_EVENT_SLAVE_RECEIVE. |
ARM_I2C_EVENT_ARBITRATION_LOST | 1UL << 6 | Occurs in master mode when arbitration is lost. |
ARM_I2C_EVENT_BUS_ERROR | 1UL << 7 | Occurs when bus error is detected. |
ARM_I2C_EVENT_BUS_CLEAR | 1UL << 8 | Occurs after ARM_I2C_BUS_CLEAR Control operation has finished. |
This callback function ((ARM_I2C_SignalEvent_t)userData)(event) is invoked in fsl_i2c_cmsis.c :
static void KSDK_I2C_MASTER_InterruptCallback(I2C_Type *base,
i2c_master_handle_t *handle,
status_t status,
void *userData)
{
uint32_t event;
switch (status)
{
case kStatus_Success: /* Occurs after Master Transmit/Receive operation has finished. */
event = ARM_I2C_EVENT_TRANSFER_DONE;
break;
case kStatus_I2C_ArbitrationLost: /*Occurs in master mode when arbitration is lost.*/
event = ARM_I2C_EVENT_ARBITRATION_LOST;
break;
default:
event = ARM_I2C_EVENT_TRANSFER_INCOMPLETE;
break;
}
/* User data is actually CMSIS driver callback. */
if (userData != NULL)
{
((ARM_I2C_SignalEvent_t)userData)(event);
}
}
KSDK_I2C_MASTER_InterruptCallback() receives the SDK I2C status, converts it to CMSIS event and invokes the callback. However, only a subset of the CMSIS events are supported/implemented. That's striking as the standard SDK peripheral drivers supports most of them.
As you know, the CMSIS driver is built on top of standard SDK peripheral drivers. The standard I2C driver fsl_i2c.c invokes the callback function after receiving the SDK I2C status from I2C_RunTransferStateMachine(). There you find, e.g. the SDK I2C status kStatus_I2C_Addr_Nak that is used when there's no target device acknowledging the I2C address. The matching CMSIS event is ARM_I2C_EVENT_ADDRESS_NACK. But the CMSIS SDK driver (as implemented by NXP) returns ARM_I2C_EVENT_TRANSFER_INCOMPLETE.
That's unsatisfying. It feels like the completion of the driver code "is left as an exercise for the reader".
While I applaud NXP that the Peripherals Tools generates code based on CMSIS API, I'd wish NXP would put more effort in code quality and API documentation.
Hope that helps future users of the CMSIS I2C driver.
Best regards,
Daniel
Solved! Go to Solution.
The driver now supports ARM_I2C_EVENT_ADDRESS_NACK, see SDK on Github.
So this issue seems to have been fixed in SDK 2.12.0
The driver now supports ARM_I2C_EVENT_ADDRESS_NACK, see SDK on Github.
So this issue seems to have been fixed in SDK 2.12.0