Automatically generating C code from a Simulink block diagram is straightforward in modern toolchains. The true engineering challenge lies in preserving the verifiable chain of evidence from top-level system requirements, to model elements, to generated source lines, and finally to target binary execution. In safety-critical sectors (automotive ISO 26262, aerospace DO-178C, industrial IEC 61508), unbroken traceability is mandatory.
The Engineering Chain of Custody
A rigorous Model-Based Design (MBD) workflow establishes an unbroken audit trail across four distinct layers:
- System & Software Requirements: Textual specifications defining control limits, response times, and fault thresholds.
- Simulink Behavioral Model: Functional blocks, Stateflow charts, and discrete-time transfer functions realizing the requirement.
- Generated C Source Code: ANSI/ISO C generated via Embedded Coder containing embedded hyperlinks and comment tags.
- Compiled Target Object Code: Machine instructions executing on the physical microcontroller.
Configuring Embedded Coder for Full Traceability
To enable seamless bidirectional navigation between Simulink blocks and generated C code, configure the following parameters in Model Configuration Settings:
- Enable Code-to-Model Navigation: In Code Generation > Report, enable “Generate code-generation report” and select “Include model-to-code traceability” and “Include code-to-model traceability”.
- Embed Requirement Tags: Connect textual requirements via Simulink Requirements so that requirement IDs appear directly as comments above generated functions and calculations.
- MISRA C Compliance: Set target language objectives to generate clean, MISRA-compliant code free from dynamic memory allocations (
malloc), recursive routines, and non-deterministic branching.
Preventing Traceability Breakdown
Traceability is most commonly compromised by five workflow errors:
- Manual Edits to Generated Files: Never modify generated
.cor.hfiles by hand. If code must be altered, modify the upstream model parameters or integrate custom code via S-Functions or Stateflow custom code blocks. - Uncontrolled Floating-to-Fixed Point Transitions: Simulating in double-precision floating point and generating single-precision or fixed-point code without explicit range/saturation analysis introduces silent numerical drift.
- Undocumented Scheduler Assumptions: Multi-rate models rely on specific execution task periods. If the target RTOS timer interrupts do not match the discrete sample rates defined in Simulink, control loop timing fails.
The Verification Hierarchy: MIL, SIL, and PIL
MathWorks defines three sequential verification phases to validate equivalence:
- Model-in-the-Loop (MIL): Verify requirements against continuous and discrete model simulations in the Simulink environment.
- Software-in-the-Loop (SIL): Compile the generated C code with a host compiler and re-run identical input test vectors, comparing numeric outputs against MIL simulation results.
- Processor-in-the-Loop (PIL): Cross-compile the generated C code with the target microcontroller toolchain, flash the binary to an evaluation board, and execute via debug interface, verifying execution time and target arithmetic.
Primary Authoritative References
- MathWorks: Embedded Coder User Guide & Model-to-Code Traceability Workflow Documentation
- ISO 26262-6: Road Vehicles — Functional Safety — Product Development at the Software Level
- MISRA C:2012 Guidelines for the Use of the C Language in Critical Systems
Conclusion
Moving successfully from Simulink to embedded C requires far more than clicking “Build”. It requires a structured development pipeline where requirements, modeling blocks, generated source lines, and target measurements can be traced forwards and backwards at every stage of the lifecycle.