Using the Clock Synchronizing Mechanism as a Handshake
The I2C protocol also includes a synchronization mechanism. This can be used as a handshake mechanism between slow and fast devices or between masters in a multi-master session.
When a slow slave (slow in terms of internal execution) is attached to the bus then problems may occur. Let's consider a serial EEPROM. The actual writing process inside the EEPROM might take some time. Now if you send multiple bytes to such a device, the risk exists that you send new data to it before it has completed the write cycle. This would corrupt the data or cause data loss.
The slave must have some means to tell the master that it is busy. It could of course simply not respond to the ACK cycle. This would cause the master to send a stop condition and retry. (That's how it is done in hardware in EEPROMs.)
Other cases might not be so simple. Think about an A/D converter. It might take some time for the conversion to complete. If the master would just go on it would be reading the result of the previous conversion instead of the newly acquired data.
Now the synchronization mechanism can come in handy. This mechanism works on the SCL line only. The slave that wants the master to wait simply pulls the SCL low as long as needed. This is like adding "wait states" to the I2C bus cycle.
The master is then not able to produce the ACK clock pulse because it cannot get the SCL line to go high. Of course the master software must check this condition and act appropriately. In this case, the master simply waits until it can get the SCL line to go HIGH and then just goes on with whatever it was doing.
There are a number of minor drawbacks involved when implementing this. If the SCL gets stuck due to an electrical failure of a circuit, the master can go into deadlock. Of course this can be handled by timeout counters. Plus, if the bus gets stuck like this, the communication is not working anyway.
Another drawback is speed. The bus is locked at that moment. If you have rather long delays (long conversion time in our example above), then this penalizes the total bus speed a lot. Other masters cannot use the bus at that time either.
This technique does not interfere with the previously introduced arbitration mechanism because the low SCL line will lead to back-off situations in other devices which possibly would want to "claim" the bus. So there is no real drawback to this technique except the loss of speed / bandwidth and some software overhead in the masters.
You can use this mechanism between masters in a multi-master environment. This can prevent other master from taking over the bus. In a two-master system this is not useful. But as soon as you have three or more masters this is very handy. A third master cannot interrupt a transfer between master 1 and 2 in this way. For some mission-critical situations this can be a very nice feature.
You can make this technique rigid by not pulling only the SCL line low, but also the SDA line. Then any master other than the two masters talking to each other will immediately back off. Before you continue, you first let SCL go back high, and then SDA, representing a stop condition. Any master which attempted to communicate in the meantime would have detected a back-off situation and would be waiting for a STOP to appear.