Design Decisions
Informative
The rationale behind the I2C driver contract. This helps implementers get the behavior right; it is not itself a requirement. Each entry points to the requirement it explains.
Why does I2cDrv have no I2cIf interface layer?
Relates to CHI-GEN-MUST-15, CHI-GEN-MUST-16.
There is no standardized interface stack above an I2C driver the way CanIf sits above a CAN
driver, so an I2cIf layer would have had no implementation and no owner — the integrator would
have written it themselves under a name implying otherwise. I2cDrv therefore declares its events as
callouts in I2c.h, which the integrator implements in the generated
I2c_Callout_Stubs.c. The full reasoning, and why Can / Lin / Mem / Wdg keep
their interface layer, is in Design Decisions.
Implication for implementers: publish the specification’s types in I2c_DriverTypes.h and the
callout prototypes in I2c.h; do not ship an I2cIf.h.
Why 7-bit addressing only?
Governs CHI-I2C-MUST-22.
The overwhelming majority of I2C devices on small ECUs use 7-bit addresses. Supporting 10-bit addressing and the general-call address would enlarge the address handling and filtering logic for a case these targets rarely need. Restricting to 7-bit keeps the driver small and the address model simple; a design that needs more can extend it.
Implication for implementers: treat deviceAddr / device_address as [0, 127]; do not
implement 10-bit or general-call handling.
Why report NACK as a callout but bus/arbitration failure as a runtime error?
Governs CHI-I2C-MUST-17.
A NACK is a normal, per-transaction outcome (the device is absent or busy) that the integration code
must handle case by case — so it is delivered through I2c_Callout_OnError alongside the
transaction. Bus and arbitration failures are node-level fault conditions better surfaced through
the common logging service LogM_Report, where system-level diagnostics collect them.
Implication for implementers: keep NACK on the transaction callout path; route bus/arbitration
faults to LogM_Report.
Why does the target stage its response in a callout?
Relates to CHI-I2C-MUST-15.
An I2C target cannot know in advance which frame the controller will address or in which direction.
Reporting the address match (with direction) and letting the integration code stage the response
with I2c_Start*Transaction keeps the data fresh and lets the same mechanism serve both read and
write without a preconfigured frame table. The configured default_data covers the case where no
response is staged in time.
Implication for implementers: drive target transfers from I2c_Callout_OnAddress; fall back to
default_data when the integration code does not respond.
Why does I2c_Init take only NULL_PTR?
Relates to CHI-I2C-MUST-09.
Configuration variants are selected at build time, not passed at runtime. Requiring
configPtr == NULL_PTR keeps the interface stable and avoids implying a runtime variant-selection
mechanism the driver does not provide.
Implication for implementers: bind the active configuration at build time; reject a non-null
configPtr as a development error.