Your ICD Defines the Bytes. It Says Nothing About When They Arrive.
Two boxes on a bench can agree on every field in the interface control document and still refuse to work together. The avionics unit sends attitude data in the format the ICD specifies, and the guidance computer reads it as written. What they disagree on is the one term the document never wrote down: when.
Open any ICD and count how much of it describes data and how little describes time. There are pages on field widths, byte order, scale factors, valid ranges, checksum placement. Somewhere near the back, if it appears at all, a line says the message is sent "at 10 Hz" or "on request." That single phrase carries the entire timing contract between two subsystems, and it is the least reviewed line in the document.
The data half of the interface gets argued to exhaustion. Two vendors will trade a dozen emails about whether a temperature field is signed. The timing half gets a nod in a meeting and a default nobody questions. Then the boxes meet on the bench, and the guidance loop that assumed fresh attitude every 20 milliseconds finds the avionics unit delivering it every 100, jittered by another 30 depending on what else is talking.
The data contract is written; the timing contract is assumed
An interface has two halves. One says what the bytes mean. The other says when they arrive, how often, in what order, and how stale they are allowed to be. Most ICDs specify the first half to four decimal places and leave the second to an assumption the two teams never wrote down or compared. "Attitude quaternion, 16-bit signed, body frame" is precise. "Rate: 10 Hz nominal" is not a contract. It says nothing about jitter, nothing about phase relative to the consumer's control cycle, nothing about what the receiver should do when a sample is late or missing.
Timing has as many terms as the data does
A complete timing contract carries at least six terms. Rate: how often the message is produced. Jitter: how far that rate may wander. Latency: how long from the sensed event to the delivered sample. Phase: where the producer's cycle sits against the consumer's. Ordering: whether messages can overtake one another. Freshness: how old a sample may be before the receiver must reject it. An ICD that names all six describes a real interface. An ICD that names only the rate has handed the other five to whoever integrates the system last, at the moment they can least afford the surprise.
A complete timing contract carries at least six terms: rate, jitter, latency, phase, ordering, and freshness.
The bus decides whether you find out early or late
Some of this is settled by the bus, if you picked one that settles anything. MIL-STD-1553 runs a command/response schedule: the bus controller decides in advance which terminal talks in which slot of a repeating major and minor frame. Timing is designed in, because nothing moves on the bus without the controller's clock. You can read a 1553 schedule and know when every message lands.
SpaceWire offers no such promise. Plain SpaceWire was built to move payload data fast, not to deliver a control message at a guaranteed instant, and its timing bends to whatever else is competing for the links. Teams that need determinism reach for SpaceWire-D, which carves the network into time-slots driven by broadcast time-codes. Neither bus is the villain here. The bus you chose already made timing decisions for you, and if your ICD does not state them, your simulator cannot check them and your integrators inherit them.
The bug hides behind every passing data check
Timing failures are hard to catch because everything about the data can be correct while the system still breaks. Mars Pathfinder landed in July 1997 and began resetting itself on the surface. Every message was well-formed. The failure was a priority inversion on the shared information bus: a high-priority task waited on a lock held by a low-priority task, while a medium-priority task ran and kept the low-priority one from releasing it. A watchdog saw the missed deadline and reset the spacecraft. No data field was wrong. A scheduling assumption was. JPL recovered the mission by enabling priority inheritance, a timing property no content-level test would ever have exercised.
That is the shape of these failures. They pass every check that reads content and fail the one nobody wrote, because the timing term lived in an engineer's head instead of in the interface.
Put timing where the data already lives
We have argued before that the interface belongs in code, with the document generated from it rather than authored beside it. Timing belongs in the same place. If the schema that defines a message can also declare its rate, its jitter budget, its latency bound, and its freshness deadline, those terms become things a build can check and a simulator can enforce. A software-in-the-loop run that models time shows a late sample as a late sample, on a Tuesday, months before the two boxes share a bench. A run that models only data shapes shows green and teaches you nothing about the failure waiting at integration.
None of this asks for a new standard. MIL-STD-1553 schedules, SpaceWire-D time-slots, ARINC 653 partition windows, and the Nyquist rate already speak in these terms. What most programs lack is the habit of treating timing as part of the interface definition instead of an operational detail to be settled later. Later means the high bay, and the high bay is the most expensive room in which to learn that 10 Hz was never fast enough.
An interface is a promise about two things: what will be said, and when. Space programs write the first promise with lawyers and review the second with a shrug. The bytes will go on arriving in perfect order, scaled and checksummed and too late to be of use, until the timing contract is written down with the same care as the data it carries.




