35,99 €
Transitioning from C can be daunting, with concerns about performance overhead, added complexity, and unfamiliar tooling. Addressing these challenges, Amar Mahmutbegovic, an advocate for modern C++ in embedded development, shows you how to harness zero-cost abstractions, compile-time checks, and powerful modern C++ capabilities to preserve performance while achieving safer, cleaner code. This book bridges the gap between traditional C and advanced C++, helping you retain the efficiency C developers demand while unlocking the safety and expressiveness of modern C++. Starting with a modern development environment setup, including a Docker container for seamless example replication, you’ll overcome the hurdles of using the C++ standard library in memory-constrained settings and get acquainted with the Embedded Template Library (ETL) as an alternative. The book walks you through essential C++ concepts before exploring advanced topics such as templates, strong typing, error handling, compile-time computation, and RAII. Through practical examples, you'll implement a sequencer, write a type-safe HAL, and apply patterns like Command, State, and Observer to solve common embedded development problems. By the end of this book, you’ll have learned how to apply modern C++ to develop robust, modular firmware with performance matching or exceeding hand-coded C solutions.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 447
Veröffentlichungsjahr: 2025
C++ in Embedded Systems
A practical transition from C to modern C++
Amar Mahmutbegović
C++ in Embedded Systems
Copyright © 2025 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
The author acknowledges the use of cutting-edge AI, such as ChatGPT, with the sole aim of enhancing the language and clarity within the book, thereby ensuring a smooth reading experience for readers. It’s important to note that the content itself has been crafted by the author and edited by a professional publishing team.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author nor Packt Publishing or its dealers and distributors will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Portfolio Director: Rohit Rajkumar
Relationship Lead: Tanisha Mehrotra
Project Manager: Sandip Tadge
Content Engineer: Rashi Dubey
Technical Editor: Tejas Mhasvekar
Copy Editor: Safis Editing
Indexer: Pratik Shirodkar
Proofreader: Rashi Dubey
Production Designer: Shankar Kalbhor
Growth Leads: Namita Velgekar and Lee Booth
First published: July 2025
Production reference: 1060625
Published by Packt Publishing Ltd.
Grosvenor House
11 St Paul’s Square
Birmingham
B3 1RB, UK.
ISBN 978-1-83588-114-9
www.packtpub.com
To my wife, Ferisa, and to my parents, Safet and Enisa, for their love and support.
– Amar
In this book, C++ in Embedded Systems, Amar Mahmutbegović shows you how to apply modern C++ for embedded systems. These systems must often run in constrained environments, with limited CPU power, memory, and electrical power, and must satisfy strict requirements for timing and reliability. They may need to avoid programming practices such as recursion and dynamic memory management.
C has long been the language of choice for embedded systems. However, C++ offers more expressive abstractions and design paradigms, better type safety, and better resource and memory safety, while retaining the low-level hardware access of C. You may have been reluctant to use C++ because of past concerns about its suitability for embedded systems. The language and its compilers have evolved over the decades to eliminate those concerns. Better type- and memory-safety mean the compiler finds more errors at compile time without runtime overhead.
Amar takes you through the features of modern C++ (through C++23) that achieve these improvements. These include techniques such as static and dynamic binding, dynamic and compile-time polymorphism, templates and metaprogramming, resource management, and compile-time computation, as well as patterns and principles that support robust design. He provides simple, practical examples written from the perspective of an experienced embedded systems developer.
He shows you how to use tools such as Compiler Explorer and Renode to examine the generated machine code and simulate embedded targets to convince yourself that these methods deliver on their promises.
The methods you learn here will help you build more reliable, flexible, maintainable, reusable, adaptable, and efficient embedded systems.
Steve Branam
Senior Software Development Engineer, Amazon Robotics
Amar Mahmutbegović is the co-founder and head of engineering at Semblie, where he leads the utilization of modern C++ for firmware development. His expertise extends to working on BLE consumer devices and medical devices, delivering sophisticated solutions for a wide range of clients, including start-ups. Amar’s dedication to innovation helps bring electronic product ideas to the world. Amar actively shares C++ benefits in the embedded community via blogs and LinkedIn. He also mentors young engineers, enhancing their skills in modern development practices. His work aims to make embedded systems more accessible, maintainable, and scalable, bridging the gap between traditional methods and modern efficiencies for developers worldwide.
My deepest thanks go to my wife, friend, and the love of my life, Ferisa Živčić, for putting up with me over the past year. Writing a book while working a full-time job took up much of my free time and energy, and I’m endlessly grateful for her patience, understanding, and support.
I am grateful to have the best parents, Enisa and Safet. They taught me the importance of learning and hard work and guided me with strong moral values.
Big thanks to all my family, friends, and colleagues who supported me and helped in any way.
Dirk Jan ten Kate is a senior embedded software engineer with over 15 years of experience in embedded systems, specializing in automotive and gas measuring industries. At his current employer, he developed a modular, hardware-independent firmware platform that forms the foundation for all new products. Dirk Jan is passionate about software quality, driving the adoption of test-driven development and continuous integration practices. His expertise spans system design, microcontroller development, RTOS, CAN, BLE, high-level communication protocols, low-level serial protocols, and programming in C and C++.
Rugved Hattekar is a skilled engineer with a strong background in embedded systems, robotics, and autonomous vehicle technology. He has developed software for safety-critical systems using C/C++, with a focus on hardware-software integration, sensor fusion, and real-time performance. At GPR, Inc., he contributed to vehicle localization and mapping systems using ground-penetrating radar. At Luminar Technologies, he works as a senior Lidar software developer specializing in embedded digital signal processing for Lidar sensors. Rugved brings deep technical insight into embedded C++ applications that drive advanced sensing and autonomous vehicle technologies.
Jacob Beningo helps embedded teams modernize their architecture, development processes, and skills to deliver high-quality, real-time systems. With two decades of experience and over 100 projects completed, he provides expert training, consulting, and coaching through Beningo Embedded Group and the Embedded Software Academy.
Preface
Part I: Introduction to C++ in Embedded Development
Debunking Common Myths about C++
Technical requirements
A short history of C++
C with Classes
Modern C++
Generic types
Ring buffer in C
Ring buffer in C++
constexpr
Bloat and runtime overhead
Constructors and destructors
Optimization
Templates
RTTI and exceptions
Summary
Challenges in Embedded Systems with Limited Resources
Technical requirements
Safety-critical and hard real-time embedded systems
Airbag control unit and real-time requirements
Measuring firmware performance and non-determinism
A-B timing and real-time execution
Sotware instrumentation with GCC
Determinism vs. Non-Determinism in Firmware
Dynamic memory management
Memory fragmentation
Safety-critical guidelines for dynamic memory management in C++
Dynamic memory management in the C++ standard library
Disabling unwanted C++ features
Summary
Embedded C++ Ecosystem
Technical requirements
Compilers and development environments
Arm Keil MDK and Arm Compiler for Embedded
IAR C/C++ Compiler and IAR Embedded Workbench for Arm
Vendor-supported IDEs and GCC
GCC
Compiler Explorer
Static analyzers
Unit testing
Profiling
Summary
Setting Up the Development Environment for a C++ Embedded Project
Technical requirements
Requirements for a modern software development environment
Compiler
Build automation
Simulator
Code editor
Containerized development environment
Building the Hello, World! program using CMake
Building a firmware using CMake
Containerized development environment and Visual Studio Code
Summary
Part II: C++ Fundamentals
Classes – Building Blocks of C++ Applications
Technical requirements
Encapsulation
Setters and getters
Static methods
Structs
Storage duration and initialization
Non-static member initialization
Default member initializers
Constructors and member initializer lists
Converting constructors and explicit specifiers
Static member initialization
Inheritance and dynamic polymorphism
Virtual functions
Virtual function implementation
UML class diagrams
Dynamic polymorphism
Summary
Beyond Classes – Fundamental C++ Concepts
Technical requirements
Namespaces
Unnamed namespaces
Nested namespaces
Function overloading
Interoperability with C
External and Language Linkage in C++
C standard library in C++
References
Value categories
Lvalue references
Rvalue references
Standard library containers and algorithms
Array
Container adaptors
Algorithms
std::copy and std::copy_if
std::sort
Summary
Strengthening Firmware – Practical C++ Error Handling Methods
Technical requirements
Error codes and asserts
Global error handlers
Asserts
Exceptions
std:: optional and std::expected
Summary
Part III: C++ Advanced Concepts
Building Generic and Reusable Code with Templates
Technical requirements
Template basics
Making a call to the template function
Template specialization
Template metaprogramming
Concepts
Compile-time polymorphism
Using Class Templates for Compile-Time Polymorphism
Curiously recurring template pattern (CRTP)
Summary
Improving Type-Safety with Strong Types
Technical requirements
Implicit conversion
Numeric promotions and conversions
Array-to-pointer conversion
Function-to-pointer conversion
Explicit conversion
const_cast
static_cast
dynamic_cast
reinterpret_cast
Type punning
Type punning – the correct way
Strong types
Summary
Writing Expressive Code with Lambdas
Technical requirements
Lambda expression basics
Storing lambdas using std::function
The command pattern
GPIO interrupt manager
std::function and dynamic memory allocation
Summary
Compile-Time Computation
Technical requirements
Templates
constexpr specifier
Example 1 – MAC address parser
Example 2 – Generating a lookup table
Generating a lookup table
Writing a signal representing the Steinhart-Hart equation
Analyzing the usage example firmware code
consteval specifier
Summary
Part IV: Applying C++ to Solving Embedded Domain Problems
Writing C++ HAL
Technical requirements
Memory-mapped peripherals
CMSIS memory-mapped peripherals
Memory-mapped peripherals in C++
Type-safe memory-mapped peripherals in C++
Modeling HSION and HSITRIM bit fields from the RCC register
Generic versions of hsion and hsi_trim
Timers
Summary
Working with C Libraries
Technical requirements
Using C HAL in C++ projects
UART interface for flexible software design
The UART interface in the Adapter pattern
Introducing static classes
Using RAII for wrapping the littlefs C library
LittleFS – a filesystem for microcontrollers
Introducing an RAII-based C++ wrapper
Cleaner file management with RAII
Summary
Enhancing Super-Loop with Sequencer
Technical requirements
Super-loop and motivation for a sequencer
Designing a sequencer
Storing a callable
Implementing a sequencer
Summary
Practical Patterns – Building a Temperature Publisher
Technical requirements
The Observer pattern
Runtime implementation
Compile-time implementation
Leveraging variadic templates
Improving the compile-time implementation
Summary
Designing Scalable Finite State Machines
Technical requirements
FSM – a simple implementation
Describing states and events
Tracking current state and handling events – the FSM class
Using the ble_fsm class
Analyzing the output
FSM – implementation using the State pattern
Understanding state class interfaces
Refactoring the ble_fsm class
Implementing the State pattern
State design pattern
State pattern implementation using tag dispatching
Boost SML
Libraries and Frameworks
Technical requirements
Standard library
Freestanding and hosted implementations in GCC
Numeric and math
<cstdint>
<limits>
<cmath>
Containers and algorithms
std::array
std:: priority_queue
std:: span
Iterators
Algorithms
Template metaprogramming
Parts of the standard library to avoid in embedded applications
Embedded template library
Fixed-size containers
Storing a callable with etl::delegate
Other utilities provided by ETL
Pigweed
Pigweed’s Sense tutorial
RPC and Protocol Buffers
Compile-time Initialization and Build
Using CIB in a temperature publisher example
Extending the temperature publisher example
Summary
Cross-Platform Development
Technical requirements
Importance of writing portable code
SOLID design principles
Single Responsibility Principle (SRP)
Open/Closed Principle (OCP)
The Liskov Substitution Principle (LSP)
The Interface Segregation Principle (ISP)
The Dependency Inversion Principle (DIP)
Testability
Summary
Other Books You May Enjoy
Index
Cover
Index
The book begins by exploring common myths about C++ and debunking them. You will gain insight into the history of C++ and develop an understanding of the zero-overhead principle. In addition, you will examine design challenges in embedded systems and learn how to address them using C++. This part also covers the embedded C++ ecosystem and guides you through setting up the development environment for a C++ embedded project, including configuring the toolchain, build system, and simulator.
This part has the following chapters:
Chapter 1, Debunking Common Myths about C++Chapter 2, Challenges in Embedded Systems with Limited ResourcesChapter 3, Embedded C++ EcosystemChapter 4, Setting Up the Development Environment for a C++ Embedded Project