Skip to main content

Best Practices

This page documents recommended practices for teams using TrinovaQ Studio in automotive embedded software development. Following these guidelines helps maintain compliance, reduce rework, and build reliable, auditable codebases.


General Development Practices

1. Scan Early, Scan Often

Run static analysis (Ctrl+Shift+I) frequently — not just before a release:

  • After completing each function or module
  • Before every code review
  • After merging or integrating changes from other team members

Why: Finding and fixing MISRA violations early is significantly less costly than doing so during a late-stage compliance review.

2. Address Issues Immediately

When a scan returns findings, address them in the same development session:

  • Fix genuine violations before moving on to new code
  • If a violation is intentional, create a deviation immediately with a complete justification
  • Never accumulate a large backlog of unresolved findings

3. Keep the Safety Score Above 90%

Set a team threshold for the Safety Score (e.g., 90%) and treat a score below that threshold as a blocker for code review approval.


MISRA C Coding Practices

4. Use Fixed-Width Integer Types

Always prefer explicit-width types over int, long, or char for data that has a known range or binary layout:

/* Preferred */
uint8_t sensor_value;
uint32_t timestamp_ms;
int16_t temperature;

/* Avoid */
int sensor_value;
long timestamp_ms;
char temperature;

5. Initialize All Variables at Declaration

/* Correct */
uint32_t counter = 0U;
float ratio = 0.0F;

/* Incorrect — uninitialized */
uint32_t counter;

Uninitialized variables are flagged as Critical findings.

6. Use Explicit Casts

Never rely on implicit type conversions. Cast explicitly and document the intent:

uint32_t address = (uint32_t)(&register_base);
int16_t diff = (int16_t)(a - b);

7. Avoid Dynamic Memory Allocation

In safety-critical embedded code, avoid malloc, calloc, realloc, and free:

  • Use statically-allocated buffers
  • Pre-allocate all data structures at startup

8. Use the Automotive Snippets

Leverage the built-in snippet library for safe, pattern-consistent code:

  • for_safe for loops with bounds checking
  • header_guard for include guards on all header files
  • fsm_secure for FSM implementations with a defensive default case

Project Organization Practices

9. Commit .trinovaq.json and Policy to Version Control

Both .trinovaq.json and .trinovaq/policy.json should be committed:

  • This ensures all team members share the same project configuration
  • Policy changes are tracked and auditable via git history
  • CI/CD pipelines use the committed configuration automatically

10. Use a Consistent Folder Structure

For multi-module projects, keep a consistent structure:

project/
├── .trinovaq.json
├── .trinovaq/policy.json
├── src/
│ ├── <module>.c
│ └── <module>.h
├── inc/
│ └── types.h # Shared type definitions
└── tara/
└── threats.csv # TARA import file

11. One Module per File Pair

Keep each source file focused on a single logical module or driver. One .c file paired with one .h file per module:

  • Reduces merge conflicts
  • Makes scan results easier to interpret
  • Simplifies per-file TARA threat mapping

Deviation Management Practices

12. Justify Precisely

A good deviation justification includes:

  • What the violation is (rule ID and specific code)
  • Why it cannot be avoided (the technical constraint)
  • Safety impact assessment (does this affect any safety goal?)
  • Compensating measure (e.g., test coverage, code review, restricted context)

Weak (unacceptable):

"This is fine, it works in practice."

Strong (acceptable):

"Rule 11.3 (pointer cast) is violated at line 47 of can_driver.c to access the memory-mapped peripheral register at its known physical address. This pattern is standard for bare-metal register access on STM32. The address and cast are verified against the reference manual. Test coverage: unit tests exercise all register access paths."

13. Zero Pending Deviations Before Release

Make it a release gate requirement that all deviations have been reviewed (Approved or Rejected). Pending deviations indicate an incomplete compliance review.

14. Minimize Deviations

Each deviation represents accepted risk. Keep the count as low as possible:

  • Fix violations whenever feasible
  • Use policy rules only for project-wide patterns, not individual cases
  • Reject deviations that should be fixed instead

Build and Compilation Practices

15. Verify Memory Metrics After Every Build

After compiling, confirm that RAM and Flash usage are within hardware limits. Approaching the limit is a risk indicator:

UtilizationAction
< 70%Normal — continue
70–90%Caution — monitor closely
> 90%Warning — plan optimization
100%+Build blocked — must reduce size

16. Match Target Hardware to Actual Device

Always set the target hardware in .trinovaq.json to match the physical device you are programming. Incorrect target selection produces incorrect RAM/Flash metrics.


Compliance Artifact Practices

17. Generate Reports at Every Milestone

Generate and archive a compliance PDF at:

  • Every sprint/iteration boundary
  • Every code review
  • Every release candidate
  • Final release

18. Maintain an SBOM for Every Release

Generate and archive a fresh SBOM at each release:

  • The SBOM should reflect the final release source set
  • Store it alongside the binary in your artifact repository
  • Submit to supply chain partners as required

19. Import TARA Before Development Starts

Import your project's TARA data before any significant development work:

  • Enables threat-aware code reviews from day one
  • Ensures threat context is available when reviewing deviations