Design Decisions
Informative
The rationale behind the MCU 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 McuDrv have no McuIf interface layer?
Relates to CHI-GEN-MUST-15, CHI-GEN-MUST-16.
There is no standardized interface stack above an MCU driver the way CanIf sits above a CAN
driver, so an McuIf layer would have had no implementation and no owner. McuDrv is also the
one module in this group that reports nothing back to its user: it defines no callouts, and so
has no Mcu_Callout_Stubs.c. Only the types header is affected, which is why it is named
Mcu_DriverTypes.h.
Whether McuDrv should gain a callout — a clock-failure notification alongside
MCU_RTERR_CLOCK is the obvious candidate — is open. The general callout mechanism in
Design Decisions is specified module-agnostically so that adding one later
needs no change to the cross-module rules.
Implication for implementers: publish the specification’s types in Mcu_DriverTypes.h;
do not ship a McuIf.h.
Why is clock stabilisation non-blocking?
Governs CHI-MCU-MUST-05, CHI-MCU-MUST-06, CHI-MCU-MUST-07.
A PLL or oscillator can take a long, hardware-dependent time to stabilise. Busy-waiting for it
inside Mcu_InitClock would stall the whole system early in boot and hide the wait from any
cooperative scheduler. Splitting the work — apply the configuration in Mcu_InitClock, poll and
distribute in Mcu_PollFunction, and expose readiness through Mcu_IsClockDistributed — lets
the integrator overlap the wait with other startup work and keeps the driver non-blocking.
Implication for implementers: never spin on a status register in Mcu_InitClock; do that in
Mcu_PollFunction and report readiness via Mcu_IsClockDistributed.
Why capture the reset reason at Mcu_Init instead of reading it live?
Governs CHI-MCU-MUST-03, CHI-MCU-MUST-09.
Reset-cause registers frequently persist across resets and must be cleared by software so the next
reset reports cleanly. If callers read the register directly and at different times, they would race
over clearing it and could miss or double-count a cause. Capturing it once in Mcu_Init (then
clearing the hardware) gives every caller a single, stable value through Mcu_GetResetRawValue.
Implication for implementers: read and clear the HW reset cause exactly once in Mcu_Init;
serve Mcu_GetResetRawValue from the captured copy (0 before Mcu_Init).
Why does the MCU driver have no de-init and no low-power modes?
Relates to CHI-MCU-MUST-01.
The McuDrv establishes the clock tree and core register state the whole system depends on; tearing that down at runtime has no meaningful use case on the target class of small MCUs, so there is no de-init. Low-power mode control (sleep / deep-sleep) is deliberately left out of standardization — it is highly device- and application-specific — rather than forcing a lowest-common-denominator API.
Implication for implementers: bring the McuDrv up once, early; expose any low-power handling through vendor-specific extensions, not the standard contract.
Why does Mcu_Init take only NULL_PTR?
Relates to CHI-MCU-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.