serial-bench / SPI / msg #3
Three identical 16-bit ADCs on one SPI bus, wired as a daisy chain so that one chip-select line clocked all three. Two of the three readings were perfect. The third - always the one physically last in the chain - came back with its two most significant bits replaced by whatever had been in the register the cycle before. The failure was completely repeatable, which on a SPI bus usually means timing rather than noise.
In a daisy chain the devices share clock and chip select, and each device's data output feeds the next device's data input. To read all three you clock 48 bits out while chip select is low: the first device's word shifts through the second and third before it reaches the master. The master's job is to hold chip select low long enough for every bit to make that journey, and to not raise it until the last bit has arrived.
Each device adds a propagation delay from its clock edge to its output changing - about 30 ns on these parts. With three in series the first device's data reaches the master 90 ns after the clock edge that launched it, on top of the half-bit the master already waits before sampling. At 8 MHz a bit is 125 ns, so 90 ns of accumulated delay is most of a bit cell, and the master was raising chip select exactly on the 48th falling edge - before the last two bits of the farthest device had propagated through the two devices in front of it.
The giveaway was which bits were wrong. A noisy bus corrupts bits at random positions; this always lost the top two bits of the last device, because those are the last to be clocked out and therefore the last to arrive. Raising chip select early simply cut the tail off the shift.
| Quantity | Value | In a 125 ns bit |
|---|---|---|
| Clock period | 125 ns | 1.00 |
| Output delay per device | 30 ns | 0.24 |
| Three devices in series | 90 ns | 0.72 |
| Master sample offset (half bit) | 62 ns | 0.50 |
| Last bit valid after 48th edge | +90 ns | 0.72 late |
The fix is embarrassingly small: hold chip select low for one extra half-bit after the 48th clock - in practice, add a short guard before raising it, or clock one or two trailing dummy bits and discard them. The driver now waits 150 ns after the final edge before releasing chip select, which at 90 ns of propagation leaves 60 ns of margin. Slowing the clock to 4 MHz also «fixed» it, for the same misleading reason it does on a mode mismatch: a 250 ns bit swallows the 90 ns delay, so the wrong behaviour hides rather than goes away.
The thing I now draw before wiring any daisy chain: the total clocks are
devices × word length, and chip select must stay low for that many clocks
plus the accumulated output delay of the whole chain. The per-device delay is tens of
nanoseconds and feels negligible until you multiply it by the chain length and compare it to the
bit cell. A two-device chain at 8 MHz is fine; a five-device chain is not, without slowing down
or adding guard time.