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.