Design Decisions

Informative

The rationale behind the Port 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 PortDrv have no PortIf interface layer?

Relates to CHI-GEN-MUST-15, CHI-GEN-MUST-16.

There is no standardized interface stack above a port driver the way CanIf sits above a CAN driver, so a PortIf layer would have had no implementation and no owner. PortDrv therefore declares its edge notification as a callout in Port.h, which the integrator implements in the generated Port_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 Port_DriverTypes.h and the callout prototype in Port.h; do not ship a PortIf.h.

Why is a pin’s function and direction fixed at Port_Init?

Governs CHI-PORT-MUST-01, CHI-PORT-MUST-02.

Pin routing is a board-level property that almost never changes at runtime, and reconfiguring a pin live is a common source of glitches (e.g. changing direction before the function mode has settled). Applying the whole pin setup once, glitch-free, in Port_Init — with no runtime reconfiguration API — keeps the driver small, keeps the electrical behavior predictable, and pushes the ordering concerns into a single, testable place. Edge detection is the one runtime-settable attribute because it genuinely varies with application state.

Implication for implementers: apply function/direction/initial-value in a glitch-free order in Port_Init; expose no runtime pin-reconfiguration API.

Why is writing an input pin left implementation-defined?

Relates to CHI-PORT-MUST-04.

Hardware disagrees on what “set an input pin” means: some MCUs use the output-register write to steer an internal pull-up/down on an input, others latch it harmlessly, and others forbid it. Rather than force a lowest-common-denominator behavior (or expensive emulation), the specification leaves it undefined so each vendor maps it to what its hardware does — and portable callers simply do not rely on it.

Implication for implementers: document your device’s Set-on-input behavior; do not assume a portable meaning.

Why a masked port write instead of a plain port write?

Governs CHI-PORT-MUST-06, CHI-PORT-SHOULD-01.

Ports usually mix pins owned by different features. A plain whole-port write would force a caller to read-modify-write and would race with other owners. Port_SetMaskedPortValue lets a caller change exactly the pins it owns in one call, and — where the hardware supports it — update them simultaneously so a coordinated change (some pins rising, some falling) takes effect atomically.

Implication for implementers: apply value & mask and leave unmasked pins untouched; prefer a single atomic HW write over a read-modify-write where possible.

Why return PORT_PIN_VALUE_LOW on a read error?

Relates to CHI-PORT-MUST-03.

The Get APIs return a value, not a status code, so they need a defined result when the pin id is invalid. PORT_PIN_VALUE_LOW is the safe default (a de-asserted line), and the development-error report tells the integrator about the bad id during development. The trade-off — a genuine LOW is indistinguishable from an error — is why callers should validate ids up front.

Implication for implementers: return LOW (all-LOW for a port) on error and raise the matching development error; do not invent an out-of-band error value.

Why does Port_Init take only NULL_PTR?

Relates to CHI-PORT-MUST-02.

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.