Naming Conventions

Informative

The naming scheme and file layout every Chiisai HAL driver follows, so that modules from different vendors look and integrate consistently. These conventions are stated normatively in the Requirements; this page explains and illustrates them.

Notation

Placeholders used throughout the specification:

Token

Meaning

<Ma>

Module abbreviation — the standardized short module name (e.g. Can, Mem, Spi).

<Vi>

Vendor infix — a vendor-specific name (abbreviation allowed).

<Ci>

Vendor API infix — represents the driver functionality (e.g. a HW instance number, or a target such as CodeFlash / DataFlash).

<Mip>

Module implementation prefix — <Ma>[_<Vi>][_<Ci>] in camel case (e.g. Mem_Vendor_Code).

<MIP>

The module implementation prefix capitalised (e.g. MEM_VENDOR_CODE).

<Ie>

Internal-file element — an optional suffix for driver-internal files (e.g. Can_Irq.c).

Module implementation prefix

Every implementation-specific symbol is built from a module implementation prefix:

<Mip> = <Ma>[_<Vi>][_<Ci>]

e.g.  Module = Mem, Vi = Vendor, Ci = Code   ->   <Mip> = Mem_Vendor_Code

The bracketed parts are optional. A microcontroller-internal driver is typically assumed to have a single instance, so the vendor/API infixes are often omitted (<Mip> = <Ma>). The vendor infix should be a vendor-specific (possibly abbreviated) name; the vendor API infix should describe the driver’s functionality.

Normative: CHI-GEN-MUST-01, CHI-GEN-SHOULD-02.

Symbol naming

Symbol kind

Pattern

Example

Enumeration literals & #define

<MIP>_<SN>

CAN_ENUMERATION

Development error values

<MIP>_DEVERR_<EN>

I2C_DEVERR_PARAM_POINTER

Runtime error values

<MIP>_RTERR_<EN>

MEM_RTERR_DATALOST

Other error values

<MIP>_ERR_<EN>

MEM_ERR_UNCLEARED

Global variables

<Mip>_<Vn>

Uart_SpecificVariable

Global functions

<Mip>_<Fn>

I2c_SpecificApi

Types

<Mip>_<Tn>Type

Wdg_External_SpecificType

(<SN> specific name, <EN> error name, <Vn> variable name, <Fn> function name, <Tn> type name.)

Normative: CHI-GEN-MUST-02.

Callout function naming

A driver reports events back to its user through functions that the driver calls and its user implements. Where those functions live, and how they are named, depends on whether the module is delivered with an upper-layer interface stack:

Module kind

Pattern

Declared in

With an upper-layer interface stack — Can, Lin, Mem, Wdg

<Ma>If_On<Event>

the interface header <Ma>If.h, and implemented by the interface stack.

Without an upper-layer interface stack — I2c, Mcu, Port, Spi, Uart

<Mip>_Callout_On<Event>

the module’s own public header <Mip>.h. These are callouts: the integrator implements them in the generated <Mip>_Callout_Stubs.c to connect their own components to the driver.

A callout always carries the Callout infix right after the module prefix, so you can tell a callout from a driver service at a glance. After that, both patterns end in On followed by the event being signalled, and the same On<Event> names are used across modules — the event vocabulary is shared:

Event

Purpose

Examples

OnReception

Indicate a completed (or partial) reception of received data.

CanIf_OnReception, Uart_Callout_OnReception

OnTransmission

Confirm a previously requested transmission has completed.

CanIf_OnTransmission, I2c_Callout_OnTransmission

OnError

Notify a detected error or fault condition.

I2c_Callout_OnError

OnChannelState

Report a channel / bus state transition.

CanIf_OnChannelState

OnWakeup

Signal a detected wake-up event.

LinIf_OnWakeup

OnEdgeDetection

Report a detected signal edge.

Port_Callout_OnEdgeDetection

Not every callout notifies an event. A callout by which the driver requests an action of the integration code is named <Mip>_Callout_<Action> — for example Spi_Callout_CsControl, with which the SPI driver asks the integration code to assert or release a GPIO chip select. Keeping On<Event> for notifications means the name shows which way the obligation runs.

The event list is open — a module names further events by keeping the On<Event> shape (e.g. LinIf_OnHeader, I2c_Callout_OnAddress, Spi_Callout_OnTransactionEnd). A worked callout file is in The Callout Stub File.

Important

Mind the missing infix. A function named <Mip>_On<Event> — with no Callout — is not a callout but an inbound notification service: the integration code calls it to tell the driver about an event the hardware cannot report on its own. Spi_OnCs is one; the integration code detects a chip-select edge and notifies the driver. Such a service is part of the driver’s API and carries a service id, and it is listed among the module’s services rather than its callouts. The infix is what tells the two apart.

Normative: CHI-GEN-MUST-15.

File naming

  • File names are case-sensitive and unambiguous (two names must differ by more than letter case alone).

  • Driver implementation files are named <Mip>[_<Ie>]*.*; the optional <Ie> part marks driver-internal files (e.g. the CAN ISR implementation lives in Can_Irq.c).

  • Each driver header — other than the general types header — carries an include guard named after the file (e.g. MEM_VENDOR_CODE_H for Mem_Vendor_Code.h).

  • The general types header contains only the types and definitions the respective driver specification defines. It is named <Ma>If_DriverTypes.h for a module delivered with an upper-layer interface stack, and <Ma>_DriverTypes.h for a module without one.

  • A module that defines callouts ships their generated default implementations in <Mip>_Callout_Stubs.c — the file the integrator edits (see The Callout Stub File).

Normative: CHI-GEN-MUST-03, CHI-GEN-MUST-04, CHI-GEN-MUST-16.

Source files at a glance

The driver files are the same either way; what differs is where the general types header comes from and who implements the functions the driver reports through.

        flowchart BT
    subgraph driver["Driver — &lt;Mip&gt;"]
        MipC["&lt;Mip&gt;.c — implementation"]
        MipH["&lt;Mip&gt;.h — public header (API + callout prototypes)"]
        CfgC["&lt;Mip&gt;_Cfg.c — generated config"]
        CfgH["&lt;Mip&gt;_Cfg.h — generated config header"]
        Ie["&lt;Mip&gt;_&lt;Ie&gt;.c / .h — optional internal files"]
    end
    subgraph iface["With an upper-layer interface stack — &lt;Ma&gt;If"]
        direction LR
        IfTypes["&lt;Ma&gt;If_DriverTypes.h — general types (spec only)"]
        IfH["&lt;Ma&gt;If.h — callback prototypes (&lt;Ma&gt;If_On*)"]
        IfC["&lt;Ma&gt;If.c — interface implementation"]
    end
    subgraph nostack["Without an upper-layer interface stack"]
        direction LR
        MaTypes["&lt;Ma&gt;_DriverTypes.h — general types (spec only)"]
        Stubs["&lt;Mip&gt;_Callout_Stubs.c — generated; integrator fills the user code blocks"]
    end

    MipC --> MipH
    MipH --> CfgH
    CfgC --> CfgH
    CfgC --> MipH
    MipC -.->|"with a stack"| IfTypes
    MipC -.->|"if callbacks used"| IfH
    MipC -.->|"without a stack"| MaTypes
    Stubs -.->|"implements the callouts declared in"| MipH
    

Source files of a driver and how they include one another (solid = always, dashed = only for that kind of module). Generated config files come from the module generator. A module with an upper-layer stack takes its general types from <Ma>If_DriverTypes.h and reports through <Ma>If.h; a module without one takes them from <Ma>_DriverTypes.h and declares its callouts in <Mip>.h, which the integrator implements in the generated <Mip>_Callout_Stubs.c. A driver may add <Mip>_<Ie> internal files (e.g. Can_Irq.c).

Include discipline

  • A driver imports only the headers it needs to realise its functionality, and exports only the information other modules need to use it.

  • A driver imports its own header, so the compiler checks the declarations against the definitions (consistency check).

Normative: CHI-GEN-MUST-05.