CppDepend
Embedded Systems — Case Study

Case Study: Managing Complexity and Ensuring Safety in Embedded Firmware with CppDepend

The client designs smart controllers used in factory automation and heavy machinery. The firmware was responsible for timing-sensitive operations like pressure control, fault detection, and…

Case Study: Managing Complexity and Ensuring Safety in Embedded Firmware with CppDepend

Industry: Embedded SystemsClient Profile: Industrial automation company developing firmware for smart controllersDomain: Real-time embedded software for sensor monitoring and actuator controlTeam Size: 20 embedded developers and testersLanguages: C and C++Key Standards: MISRA C, CERT C, ISO/IEC TS 17961Hardware Targets: ARM Cortex-M, RTOS (FreeRTOS-based)

The Challenge

The client designs smart controllers used in factory automation and heavy machinery. The firmware was responsible for timing-sensitive operations like pressure control, fault detection, and communication with upstream systems over industrial protocols (CANopen, Modbus).

As the firmware evolved, the team faced several pain points:

  • Complex, tightly coupled modules were hard to test or reuse across product lines.
  • Compliance with MISRA C and internal reliability rules was enforced manually via spreadsheets and checklists.
  • Developers frequently introduced memory risks, deep recursion, and unsafe type conversions that weren’t caught until late testing.
  • Legacy drivers and middleware from third-party vendors violated architectural boundaries and bloated system complexity.
  • Managers had no visibility into technical debt or code health trends, making sprint planning and risk mitigation harder.

The team needed a tool to automate enforcement of safety and design rules, measure maintainability, and provide early feedback on risky code — without adding overhead or disrupting the real-time constraints of the system.

The Solution: CppDepend

CppDepend was introduced to help the team gain control over growing firmware complexity and ensure code safety for long product lifecycles. It was selected over simpler linters because of its architecture enforcement capabilities, trend dashboards, and flexible CI integration.

Key goals:

  • Automate detection of MISRA C and CERT C violations
  • Identify hidden cyclic dependencies and architecture leaks
  • Track technical debt, complexity, and code churn over time
  • Help guide refactoring efforts for modularity and reuse
  • Support testability and system certification documentation

Implementation Approach

Week 1–2: Firmware Baseline

  • Scanned firmware (~300K LOC)
  • Detected:
  • 800+ MISRA violations
  • Several circular dependencies between I/O and business logic
  • 60+ functions with high cyclomatic complexity or excessive nesting

Week 3–4: Custom Rule Definition

  • CQLinq rules created to catch:
  • Prohibited use of dynamic memory or malloc
  • Deep recursion beyond 2 levels
  • Volatile usage outside hardware abstraction layer
  • Design-layer rules defined (e.g., HAL must not depend on App logic)

Week 5–6: CI Integration & Reporting

  • Added CppDepend to nightly builds in Jenkins
  • Generated HTML dashboards for review by QA and firmware leads
  • Used trend reports to detect creeping complexity across components

Results After 6 Weeks

MetricBefore CppDependAfter 6 Weeks
MISRA/CERT rule violations800+120
Function complexity violations60+15
Architecture rule violations40+8
Regression bugs due to layeringFrequentRare
Manual review overhead (avg/Sprint)~12 hours< 3 hours

Outcomes & Benefits

  • Cleaner Architecture: Developers could now refactor and decouple modules with confidence, leading to faster reuse across product variants.
  • Improved Code Safety: High-risk patterns like deep nesting, unsafe casting, or unexpected includes were caught early.
  • Testability Increased: By enforcing layering and modularity, teams could better isolate units for embedded testing.
  • Audit-Ready Documentation: Reports were reused in internal quality audits and external client reviews.
  • Reduced Developer Fatigue: Instead of policing one another in code reviews, teams relied on CppDepend to enforce rules consistently.

Why CppDepend?

CppDepend was not just a static analyzer — it was a design governance tool. It allowed the team to transition from reactive, checklist-driven compliance to proactive, automated quality assurance.

Its low-friction integration, rich code model, and customizable rules made it suitable for deeply embedded software with long-term product support.

Conclusion

CppDepend helped the team reclaim control over their embedded firmware. It reduced review time, increased modularity, and gave engineers and managers alike the visibility they needed to build safe, scalable, and testable embedded systems— ready for deployment in high-reliability industrial environments.

← Back to Embedded Systems overview

See what CppDepend reveals in your codebase

Run the analysis on your own projects: coding standards, architecture validation, technical debt and quality gates — in minutes.