I²C · Module 24
Reasoning About Multi-Master Arbitration
Arbitration worked on a waveform rather than from a definition: what a controller can know, why the winner never learns it won, and a measured comparison of three loss-detection rules — one missing 9.3 % of losses entirely, another driving for six more bits onto the winner’s transfer.
Two controllers decide, independently and at the same instant, to start a transfer. There is no referee, no shared state, no channel for them to negotiate on, and neither knows the other exists. Within a few microseconds exactly one is transmitting and the other has withdrawn without a single byte being lost.
The mechanism is remarkable and it is also almost entirely a consequence of one fact already established in 2.5. What this chapter works is the part that is genuinely hard: reasoning about a system in which no participant has a complete view, and turning that into what a controller must do and when.
1. What a Controller Can Know
This is the whole problem, and it fits in a table.
| a controller knows | a controller does not know |
|---|---|
| what it is driving, bit by bit | whether anyone else is on the bus |
| what the resolved line reads | who else is transmitting, or what |
| that those two differ, when they do | whether it won |
| the protocol rules | when it is safe to assume it is alone |
The third row is the only new information the bus ever supplies, and it is available in exactly one circumstance: the controller released the line and the line came back low. If it pulled low, the line is low and it has learned nothing — its own pull explains the reading completely.
So a controller's entire knowledge of the outside world is a one-bit signal, available only on the bits where it transmitted a 1. Everything below follows from that.
2. The Mechanism, on a Waveform
Read the first two bits again. A and B are transmitting identical bits, so the bus carries what both intended, and neither has learned anything. This is the ordinary case at the start of every simultaneous transfer, because the first bits of an address are often shared across a family of devices. Arbitration is not a contest that begins at the START — it is a running comparison that only produces information at the first bit where the two disagree.
The third bit is the decision. A drives 1 (releases), B drives 0 (pulls). Wired-AND gives 0. A is comparing its intent against the line, sees 1 against 0, and that single observation is the entire notification. There is no arbitration-loss signal on the bus, no acknowledge, no timing. One bit differing from one line.
3. The Winner Never Knows It Won
B, on that same bit, pulled low and read low. Its intent and the line agree. B has learned nothing, and continues transmitting exactly as it would have on an empty bus.
This is not an oversight in the protocol. It is the property that makes arbitration non-destructive:
- The winner's transfer is never interrupted, delayed, or altered. It does not need to be told it won, because nothing about its behavior would change.
- The loser withdraws without transmitting anything, so no byte was corrupted and no retry protocol is needed.
- No arbitration-specific signalling exists at all — no extra wire, no extra bit, no extra state.
The cost is that "I am not aware of having lost" is not the same as "I am alone on the bus", and no amount of monitoring makes it so. A controller cannot ever establish that it is the only one; it can only establish that it has not yet been contradicted. Any design that relies on knowing the bus is exclusively its own needs something outside I²C to provide that.
4. The Fourth Bit: Why "Immediately" Means Immediately
The fourth bit in the figure is the part that matters for RTL.
Having lost, A must stop driving. If it does not, its next bit lands on B's transfer — and on that bit, B released and A pulled, so the bus reads 0 where B intended 1. B is monitoring correctly, and B concludes it has lost.
Both controllers now believe they lost. The bus is idle; B's transfer was destroyed mid-byte; and whatever partial byte reached the addressed target was a mixture of two transmissions. There is no participant anywhere in the system with enough information to reconstruct what happened — and this is a failure that a correctly-implemented A and a correctly-implemented B cannot produce. It requires a defect in one of them, and its symptom appears in the other.
That is the structural reason the rule is "stop driving on the bit you detect the loss", not "stop at the end of the byte". The loser's obligation is not politeness; it is the thing standing between a clean handover and a collision that corrupts a third party's data.
5. Three Detection Rules, Measured
A controller has to decide when to compare. Three plausible rules, run over the same traffic:
- R1 — compare intent against the resolved line at every bit. The rule.
- R2 — compare only during the data bytes, not the address. A common simplification, on the reasoning that the address is short and mismatches there are rare.
- R3 — compare once, at the end of each byte. Cheaper: one comparison per byte instead of nine.
2000 random two-master frames; master A lost in 1985 of them.
rule missed mean bits driven after losing worst case
R1 every bit 0 0.00 0
R2 data bits only 184 8.24 16
R3 end of byte only 0 5.87 8R1's zeros are true by construction — it detects at the bit the loss occurs, because that is the definition of both. It is the reference, not a result. The other two rows are the results, and both are worse than they look.
R2 misses 9.3 % of losses entirely. 184 of 1985. Those are frames where A lost during the address byte and, in the data byte that followed, never happened to release a bit that B was pulling. A never detected anything, drove its complete frame onto B's transfer, and reported success. The rate is not a fluke of one seed: across four seeds it ranged 170–184 misses with the mean bits-late between 7.96 and 8.24.
Worse, losing in the address phase is not the rare case — it is the common one, because two controllers addressing different targets diverge in the address by construction. R2 skips exactly the region where arbitration usually happens, on the reasoning that it is rare there.
R3 never misses, and drives for six more bits on average. Mean 5.87, worst case 8. Every one of those bits is A's data being pulled onto a transfer B is conducting, and §4's mechanism means most of them will also make B believe it has lost. R3 converts a clean arbitration into a mutual failure, reliably, while reporting that it detected the loss.
| R1 every bit | R2 data bits only | R3 end of byte | |
|---|---|---|---|
| losses missed entirely | 0 | 184 of 1985 (9.3 %) | 0 |
| mean bits driven after losing | 0 | 8.24 | 5.87 |
| worst case | 0 | 16 | 8 |
| comparisons per byte | 9 | ~9 on one byte | 1 |
| corrupts the winner's transfer | no | yes | yes |
The saving R3 offers is eight comparisons per byte of a one-bit equality test. That is the trade on the table: a negligible amount of logic against reliably corrupting another controller's data on every arbitration event.
6. What the Loser Must Do Next
Detection is the hard part; the response is short, and each item is there because of a specific failure.
Stop driving SDA on that bit. §4 — otherwise the winner is corrupted and may conclude it lost too.
Do not send a STOP. This is the one that catches people. A STOP releases the bus, and the bus is not the loser's to release — B is mid-transfer. A STOP issued by the loser terminates the winner's transaction, and the addressed target will act on it. "Abandon the transfer" and "signal the end of a transfer" are different operations and only the first is permitted here.
Keep monitoring. The loser must track the winner's traffic to know when the bus becomes free, which means recognising the winner's STOP. A controller that stops observing after losing does not know when it may retry.
Retry from the beginning, after the bus-free interval. Not from the byte it reached — the target never received a complete, addressed transaction, so there is no partial state to resume. 13.4 works the recovery sequence.
Do not treat it as an error. Losing arbitration is a normal event on a multi-controller bus, and a design that reports it as a fault will report faults proportional to bus activity. It belongs in a counter, not an interrupt handler's error path — though the counter is worth having, because a rate that changes is diagnostic in a way an anecdote is not.
One case deserves its own mention. A controller may lose arbitration while addressing a target and be the target of the winning transfer. It must switch roles mid-frame: stop driving, and then respond as a target to an address it is simultaneously failing to transmit. A design that treats controller and target as mutually exclusive modes cannot do this, and the failure is a device that goes deaf exactly when another controller wants to talk to it.
7. What Arbitration Does Not Resolve
Three limits, and each one is a place where designs quietly assume more than the mechanism provides.
Two controllers sending identical bytes both "win." If A and B transmit the same address, the same direction and the same data, no bit ever disagrees and neither detects anything. The target sees one well-formed transfer and acknowledges it. This is harmless when the transfers are genuinely identical — the intended effect happens exactly once — and it stops being harmless the moment the transfers diverge later, at which point arbitration resumes mid-transaction, with one of them having already committed to a read it cannot complete.
Arbitration decides SDA, not SCL. Two controllers clocking at different rates are resolved by a separate mechanism — clock synchronization, where the wired-AND on SCL produces a low phase as long as the slowest participant's and a high phase as short as the fastest's (13.2). Arbitration and synchronization are often described as one topic and are two independent consequences of the same wired-AND.
Arbitration does not bound latency. A controller that keeps losing keeps retrying. There is no fairness mechanism, no priority, no queue. On a bus where one controller is much busier than another, the quiet one can be starved indefinitely, and nothing in I²C prevents it. If bounded latency is a requirement, it has to come from a layer above — a schedule, a token, or a different bus.
8. Verification Consequences
Arbitration is among the hardest I²C behaviors to verify well, for a reason worth naming precisely: the interesting quantity is invisible to a data check.
A controller that loses arbitration correctly transfers nothing. A controller that loses and keeps driving corrupts somebody else's transfer — so the mismatch, if anything catches it, appears on a different agent's transaction. A scoreboard organised per-controller sees a loser that transferred nothing (correct) and a winner whose data was wrong (attributed to the winner).
Three practical consequences:
The checker must read the resolved line. A monitor sampling a controller's drive intent reports the byte that controller meant to send, which during an arbitration loss is a byte that was never on the wire. 24.1 §4 measures this: intent monitor reports 0xA5, wire carried 0xA1, and on a single-controller bus the two agree perfectly forever.
The oracle is the wired-AND of the intents. Computable from the stimulus by the protocol rule, never read from a device. That is what makes a two-controller test self-checking at all.
Randomly generated pairs discriminate poorly. Over 2000 random frames, A lost in 1985 — arbitration happened almost always, but where it happened was concentrated in the first couple of bits, because two random bytes usually diverge early. The cases with information in them are the constructed ones: divergence at the last address bit, at the R/W bit, in the acknowledge slot, and the identical-byte case of §7 where nothing diverges at all. Directed stimulus is not a supplement here; it is where the coverage actually is.
9. Common Misconceptions
"The winner is notified that it won." Nothing notifies it. The winner's observations are identical to those it would make alone, which is exactly what makes arbitration non-destructive — and it means no controller can ever establish that it has the bus to itself.
"Arbitration is a contest at the START." It is a running comparison across every bit, producing information only at the first disagreement. Two controllers can transmit identically for a whole address byte before anything is decided.
"The loser should send a STOP to clean up." The bus is not its to release. A STOP terminates the winner's transaction and the target will act on it. The loser withdraws silently.
"Detecting at the end of the byte is close enough." Measured: an average of 5.87 bits of the loser's data pulled onto the winner's transfer, worst case 8 — and by §4 most of those cause the winner to conclude it lost too. The saving is eight one-bit comparisons per byte.
"The address is short, so we can skip arbitration checking there." Losing during the address is the common case, because two controllers addressing different targets diverge in the address by definition. Measured: skipping it misses 9.3 % of losses completely, with the loser transmitting its entire frame onto another transfer and reporting success.
"Losing arbitration is an error." It is the mechanism working. A design that raises an error on it generates errors proportional to how busy the bus is.
Two multi-controller buses, and what each one's symptom pointed at
1The controller whose data appeared inside another controller's transfer
// Two controllers on one bus. Controller A is a small MCU with a bit-banged
// I2C implementation; controller B is a hardware block in an SoC.
//
// A's arbitration check, which its author considered thorough:
//
// for (i = 7; i >= 0; i--) {
// sda_write(byte & (1 << i));
// scl_release(); while (!scl_read()) ;
// if (i == 0) { // <-- once, at the end
// if (sda_read() != (byte & 1)) arbitration_lost();
// }
// scl_drive_low();
// }
//
// One comparison per byte. It DOES detect -- it just detects late, and every
// bit between the loss and the detection is A pulling on B's transfer.B's transfers occasionally carry bytes that B never sent -- values that turn out, on inspection, to be fragments of A's intended payload. B's own hardware reports arbitration loss on some of those transfers, which is confusing because B has the faster clock and "should" win.
B is not losing. B is being CORRUPTED by A, and B's arbitration checker -- which is correct -- reads a released line as low and draws the only conclusion available to it.
Measured over 2000 random frames, end-of-byte detection leaves the loser driving for a mean of 5.87 more bits and a worst case of 8. Each of those is a bit where A may pull low while B releases, and every such bit both destroys B's data and makes B believe it lost.
The tell that separates this from an ordinary arbitration problem is that the CORRUPTED bytes are meaningful -- they are A's payload, not noise. A collision between two well-behaved controllers never produces that, because a correct loser stops driving before it has transmitted anything.
Compare on every bit the controller releases, which is where the only
information is:
for (i = 7; i >= 0; i--) {
bit = (byte >> i) & 1;
sda_write(bit);
scl_release(); while (!scl_read()) ;
if (bit == 1 && sda_read() == 0) { // released and read back low
arbitration_lost(); // stop driving NOW
return;
}
scl_drive_low();
}
Note the guard. The comparison is meaningful ONLY when the controller released
-- if it pulled low, the line is low because of its own pull and no information
exists. Comparing unconditionally is harmless here but hides that reasoning,
and it is the reasoning that tells you the check belongs on every bit rather
than on some of them.
Cost: eight one-bit comparisons per byte.2The device that went deaf whenever the other controller was busy
// A device that is BOTH a controller (it reports events on its own initiative)
// and a target (the host reads its registers). The implementation has a mode:
//
// if (mode == MASTER) { drive the transfer; }
// else { watch for our address; }
//
// The two are mutually exclusive, which seemed obviously right -- a device is
// doing one or the other.
//
// It is not right when the device loses arbitration to a host that is
// addressing THE DEVICE ITSELF. It stops driving, correctly, and stays in
// MASTER mode waiting to retry -- while the winning transfer on the bus is
// addressed to it.The host reports NACKs from the device, but only sometimes, and only when the device has its own report queued. A bus capture shows the address going out, the ninth clock arriving, and nobody acknowledging. The device's own logs show it attempting a transfer at that moment and recording an arbitration loss.
Both halves of the device are behaving as designed and the design's premise is wrong. Controller and target are not mutually exclusive ROLES on I2C -- they are mutually exclusive only in the sense that a device cannot drive its own address to itself. The moment it loses arbitration, it must become a target for the frame in progress, because the frame in progress may be addressed to it and it is the only device that can answer.
The window is narrow, which is why it looks intermittent: it requires the device to start a transfer in the same bit period as the host, and the host's transfer to be addressed to the device. On a bus where the device reports rarely, that can take weeks to hit.
On arbitration loss, do not return to idle -- ENTER TARGET MODE for the frame
already in progress, and keep the pending transfer queued for retry after the
winner's STOP:
on_arbitration_lost():
release_sda();
pending_retry = current_transfer; // retry after the bus is free
enter_target_mode(); // the frame in flight may be ours
// the address bits are STILL ARRIVING -- the shift register that was
// comparing them for arbitration already holds them
That last comment is the part worth keeping: the bits needed to decide whether
the frame is addressed to this device are the same bits the arbitration
comparison was already looking at. The switch costs no additional sampling --
only the recognition that the two roles share a datapath.10. Reason It Through
A. Two controllers start simultaneously. One is addressing device 0x50 for a write; the other is addressing 0x51 for a write. Which wins, and at which bit is it decided?
0x50 is 1010000 and 0x51 is 1010001, both with R/W = 0. The first six address bits are identical, so nothing is decided there — the bus carries what both intended and neither learns anything. They diverge at the last address bit, where 0x50 drives 0 and 0x51 drives 1. Wired-AND gives 0, so the 0x51 controller released and read low: it has lost, at the seventh bit of the first byte. 0x50 wins and never knows there was a contest. Two things are worth extracting. The lower address wins, because a 0 always beats a 1 on a wired-AND — which means address allocation silently determines arbitration priority. And six of the seven bits produced no information at all, which is why an implementation that only samples occasionally can appear to work for a long time.
B. A controller keeps a counter of arbitration losses. Over a week it reads 40 000. Is that a problem?
Not by itself — it is a measure of contention, and on a bus with two active controllers a high count means the mechanism is working. What makes it interpretable is the ratio to attempted transfers and the trend. If it is 40 000 losses out of 45 000 attempts, this controller is being starved, and since I²C has no fairness mechanism it will stay starved as long as the other one is busy; that is a system design problem needing a layer above I²C. If it is 40 000 out of 4 million, it is background. The change in rate is more diagnostic than the value: a count that jumps after a firmware update points at a new traffic pattern, and one that rises with temperature points at something electrical being read as a loss — a released line reading low because it did not rise in time is indistinguishable, at the comparison, from a real arbitration loss.
C. Why can a scoreboard that checks each controller's transactions independently miss an arbitration defect entirely?
Because the defect's consequence lands on the other controller. A loser that keeps driving transfers nothing of its own — correct, from its own transaction's point of view — while corrupting the winner's bytes. Per-controller, the loser looks right and the winner looks like it produced bad data, so the investigation goes to the winner, which is the correct design. Catching it requires a check on the resolved line against the wired-AND of both controllers' intents: an oracle that exists only at the bus level and that no per-agent view can construct. This is the same structural point as 24.2 §2 — the expected value has to come from somewhere that spans the thing being checked.
D. A design team proposes detecting arbitration loss by comparing at every bit, but sampling the line one clock after SCL rises rather than in the middle of the high phase, to avoid a timing path. What could go wrong?
The comparison becomes sensitive to rise time, and it fails in the direction that produces false losses rather than missed ones — which is the less dangerous direction but is still a real failure. A released line reading low is the definition of a loss, and a slowly-rising line reads low for a while after SCL goes high. Sampling early therefore reports a loss on a bus where nothing is contending, and the rate will track exactly the things rise time tracks: speed mode, position on the bus, temperature, and whatever was added to the harness last. A controller that abandons transfers spuriously on a single-controller bus is a genuinely confusing failure, because arbitration loss is the last thing suspected when there is nobody to arbitrate against. The question to answer before agreeing is not whether the timing path closes but what the worst-case rise time is at the target speed mode, and whether the sampling point is inside the valid window that 24.5 §3 sizes — which makes this a pull-up question wearing an RTL costume.
11. Understanding Check
12. What 24.7 Settled
A controller's knowledge of the outside world is one bit, available in one circumstance. It released the line and the line came back low. Everything about arbitration follows from that, including its limits.
The winner never learns it won, and that is the design. It is what makes the mechanism non-destructive, and it is why no controller can establish that it has the bus to itself.
"Stop immediately" is structural, not stylistic. A late withdrawal pulls the loser's data onto the winner's transfer and makes the winner believe it lost. Measured: end-of-byte detection leaves an average of 5.87 bits and a worst case of 8 doing exactly that.
Skipping the address byte misses the common case. Measured: 184 of 1985 losses undetected, with the loser transmitting its entire frame onto another transfer and reporting success. Two controllers addressing different targets diverge in the address by construction.
Three things arbitration does not do. It does not resolve identical transmissions, it does not decide SCL — that is clock synchronization, a separate consequence of the same wired-AND — and it provides no fairness, so a busy controller can starve a quiet one indefinitely.
The verification oracle has to be the wired-AND of the intents. Nothing read from a device can serve, and no per-controller view can attribute a late-withdrawal defect to the controller that caused it.
The three reasoning chapters have each taken one mechanism and worked it end to end. The last chapter puts them back together under the constraint that makes all of it harder — no notes, no simulator, and somebody waiting for an answer. Chapter 24.8 — Designing an I²C Master at the Whiteboard.
Continue learning
Related tutorials
- Related topic
I²C SDA Arbitration — Wired-AND Decides Bit by Bit
Arbitration with no arbiter, no priority and no protocol exchange — resolved by one asymmetric test each master performs on itself. Settles what 'no information is lost' actually means.
- Related topic
Wired-AND — Many Drivers, One Line, No Contention
Put several open-drain devices on one node and a logic function appears in the wiring: any participant asserting LOW wins, and HIGH requires unanimous release. Derive dominant LOW, see why two devices pulling together is agreement rather than conflict, and watch three of the protocol's mechanisms become predictable.
- Related topic
The Shared Bus — Many Targets, Sometimes Many Masters
One pair of conductors serves an entire board. Physically the bus is a broadcast medium — every device sees everything — while participation is logically selective. That gap is the central abstraction of I²C, and it also opens the multi-controller case.
- Related topic
Why Multiple I²C Masters Exist
The systems that end up with two masters on one bus, and the rule that is not enough to keep them apart. Includes the finding that a collision leaves no trace on the wire.
