When you implement I2C and/or SSI you must implement timeouts and anit-lockup code.
Both busses are driven with statements like
while(some flag) wait forever.
And you can get locked up if there is a single clock glitch.
void I2CResetLoopTimer(int i2cDeviceIdx)
{
xI2CConfigHandle h = I2CDevices[i2cDeviceIdx];
h->loopTimer = xTaskGetTickCount();
}
int I2CHasError(int i2cDeviceIdx)
{
xI2CConfigHandle h = I2CDevices[i2cDeviceIdx];
portTickType dt = xTaskGetTickCount() - h->loopTimer;
return dt > 200 ||
I2C_GetFlagStatus(h->i2cDevice, I2C_FLAG_TIMEOUT) ||
I2C_GetFlagStatus(h->i2cDevice, I2C_FLAG_PECERR) ||
I2C_GetFlagStatus(h->i2cDevice, I2C_FLAG_AF) ||
I2C_GetFlagStatus(h->i2cDevice, I2C_FLAG_ARLO) ||
I2C_GetFlagStatus(h->i2cDevice, I2C_FLAG_BERR);
}
int I2CHasErrorAndClear(int i2cDeviceIdx)
{
if(I2CHasError(i2cDeviceIdx))
{
I2CClearError(i2cDeviceIdx);
return true;
}
return false;
}
And an example loop.
int WhileBusy(int i2cDeviceIdx)
{
xI2CConfigHandle h = I2CDevices[i2cDeviceIdx];
I2CResetLoopTimer(i2cDeviceIdx);
while (I2C_GetFlagStatus(h->i2cDevice, I2C_FLAG_BUSY))
{
if(I2CHasErrorAndClear(i2cDeviceIdx))
{
return false;
}
portYIELD();
}
return true;
}
TF