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.