|
PER Firmware
|
The CANpiler is the centralized code generation authority. It handles CAN message generation, fault library, and (soon) daq variable generation.
Modeled After the traditional compiler pipeline. Written in python for ease of maintainence and development.
build.py: Main entry point for CANpiler. Coordinates the top-level data flow.
templates/: Directory containing Jinja2 templates for all generated build artifacts. Decouples the output formatting from the generation logic.
validator.py: Catches syntax errors in the configuration files using json_schema library.
parser.py: Parses configurations into IR @dataclasses. "Logical" config errors are caught during this phase.
SystemContext for subsequent stages.linker.py: Transforms the IR into a linked IR with resolved message IDs using a two-pass "Water Level" algorithm.
msg_id_override values respect priority monotonicity (messages in priority $N$ cannot have IDs higher than messages in priority $N+1$).msg_name to ensure deterministic builds.mapper.py: Maps CAN IDs to physical hardware resources.
accept_all_messages is enabled.Produces the final build artifacts from the SystemContext using the Jinja2 templating engine.
static constexpr for type-safe constants and identifiers.codegen.py: Generates node headers with packed bit-field structs and endianness-safe accessors. Includes hardened sign-extension logic for signed signals.dbcgen.py: Produces deterministic, versioned DBC files using the cantools library.faultgen.py: Injects FAULT_SYNC and FAULT_EVENT messages into node configurations and generates global fault tracking maps (fault_data.c/h).load_calc.py: Performs post-generation capacity analysis for each bus in the system.
CAN_check_stale(), which marks received messages as stale if they have not been updated within 2.5x their expected transmission period.