Hi
I am not sure that it is fully releated but I have found the following to realiably reset the I2C master when a bus busy is detected (in the particular case due to loss of arbitration):
ptrI2C->I2C_C1 &= ~(I2C_IEN); // disable I2S to clear busy
fnDelayLoop(100); // short delay before re-enabling the I2C controller (without delay it doesn't generate any further interrupts)
ptrI2C->I2C_C1 |= (I2C_IEN); // re-enable
If the slave is in a state in which it blocks the bus by holding the data line low the following unlocking sequence soves it:
1. Program the I2C lines as GPIO; SDA as input and SCL as output
2. clock SCL 'manually' until slave frees the data line
while (_READ_PORT_MASK(A, PORTA_BIT10) == 0) { // if the SDA line is low we clock the SCL line to free it
_CONFIG_DRIVE_PORT_OUTPUT_VALUE_FAST_LOW(A, PORTA_BIT11, 0, (PORT_ODE | PORT_PS_UP_ENABLE)); // set output '0'
fnDelayLoop(10);
_CONFIG_PORT_INPUT_FAST_LOW(A, PORTA_BIT11, (PORT_ODE | PORT_PS_UP_ENABLE));
fnDelayLoop(10);
}
3. Program pins as I2C again
Regards
Mark