Integration Guidelines
Informative
How a Chiisai HAL driver is packaged, configured, and wired into a project — the integrator’s view. The binding rules behind these guidelines live in the Requirements.
Package layout
Each module package follows a common directory structure.
Only the <Mip> folder may be extended
with further sub-folders (next to the three standard ones);
Documentation, Generator, and Implementation are leaf folders that contain files only, with no nested sub-folders:
<InstallDir>
└─ <Mip> # extra sub-folders may be added here, next to the three below
├─ Documentation the module's specification / documentation files # files only — no sub-folders
├─ Generator generator scripts and template files # files only — no sub-folders
└─ Implementation implementation sources # files only — no sub-folders
Normative: CHI-GEN-MUST-06.
Modules with and without an upper-layer stack
Whether a module has an upper-layer interface stack is fixed by its specification, and it determines both where the driver’s general types header comes from and who implements the functions the driver reports events through (the layering view is in Architecture and Layering):
With an upper-layer stack |
Without an upper-layer stack |
|
|---|---|---|
Modules |
|
|
General types header |
|
|
Events reported through |
|
|
Integrator writes |
code above the interface stack |
the user code blocks in |
flowchart LR
subgraph withstack["Module with an upper-layer stack"]
direction TB
Driver1["Chiisai HAL driver (<Mip>)"]
IfTypes["<Ma>If_DriverTypes.h<br/>from the upper-layer stack<br/>(CanIf / LinIf / …)"]
IfFns["<Ma>If_On* implemented<br/>by the stack"]
Driver1 -->|"includes"| IfTypes
Driver1 -->|"reports through"| IfFns
end
subgraph nostack["Module without an upper-layer stack"]
direction TB
Driver2["Chiisai HAL driver (<Mip>)"]
MaTypes["<Ma>_DriverTypes.h<br/>published by the module"]
Callouts["<Mip>_Callout_On* implemented by<br/>the integrator in <Mip>_Callout_Stubs.c"]
Driver2 -->|"includes"| MaTypes
Driver2 -->|"reports through"| Callouts
end
Where a driver’s general types header comes from, and who implements the functions it reports through. A module with an upper-layer stack (left) gets both from that stack; a module without one (right) publishes its own types header and declares callouts that the integrator implements in the generated stub file.
Connecting your components via the callout file
For a module without an upper-layer stack, the module generator emits
<Mip>_Callout_Stubs.c: one default, empty implementation of every callout the active
configuration enables. This is the file an integrator edits — it is the seam between the driver and
the integrator’s own components.
Fill in the user code blocks. Each callout body contains a user code block delimited by
USERBLOCKmarkers naming that callout. Put your code inside the markers and leave the markers themselves untouched — the generator finds your code by them.What survives regeneration. Everything inside a user code block, including the block for your own
#includedirectives. Anything you write outside the blocks is generator-owned and will be replaced.Callouts you have not configured. These are still emitted, but excluded from compilation (inside
#if 0), so code you wrote for a callout is not lost if you disable and later re-enable the corresponding event.What you must not do. Do not rename the file, move a callout out of it, or edit the marker comments; and do not rely on a callout being reached from a particular context — a callout may be invoked from an interrupt or from the module’s
PollFunctiondepending on configuration, so keep the body short and re-entrancy-safe as documented for that callout.
The complete file skeleton, annotated, is in The Callout Stub File. Each module’s own callouts and their exact contract are listed in that module’s API reference.
Normative: CHI-GEN-MUST-14, CHI-GEN-MUST-15, CHI-GEN-MUST-16.
Dependency management
A driver imports only the headers required for its functionality and exports only what other modules need — keep the coupling surface small.
Only the general types header is exempt from the per-file include-guard rule; every other header carries a guard named after the file.
A driver includes its own header so the toolchain can check declarations against definitions.
Configuration and build flow
A driver is configured through a configuration model, not by hand-editing generated code. Each module ships:
a configuration-model definition (the
<Mip>Modelroot, with ageneralsection and aconfig_setsection);a generator script and templates that turn a validated configuration into the driver’s configuration sources.
Configuration naming follows a fixed style — UpperCamelCase for model classes, snake_case
for properties, SNAKE_CASE for enumeration values — and vendor-specific properties are prefixed
ext_ so they are clearly separable from the standardized set. The detailed model and the
per-module property tables are in each module’s configuration reference (for the CAN example, see
Configuration Reference).
Normative: CHI-GEN-MUST-12.
Interrupts and critical sections
Interrupt handlers are defined with the common
ISR()macro rather than a raw, compiler-specific handler signature, so handler definitions stay portable across toolchains.Where a driver needs exclusive access to shared state, it brackets the region with the common
<Mip>_EnterCriticalSection/<Mip>_ExitCriticalSectionservices, which the integrator supplies. A driver keeps these regions as short as possible.
The exact signatures of the ISR() macro, the critical-section services, the logging service
(LogM_Report), and the shared types are defined in the Reference
and referenced from each module.
Normative: CHI-GEN-MUST-10, CHI-GEN-MUST-11.