Course Outline: Object-Oriented Programming on Microcontrollers (C++)

1. Introduction to C++ in Embedded Systems

Motivation and History

  • Evolution from C to C++ and Modern C++ (C++11 to C++26).

  • Motivation for using C++ in the embedded sector.

  • Comparison of C, C++, Java, and Python in embedded contexts.

  • Challenges of using C++ on microcontrollers (e.g., memory fragmentation).

Build Process and Environment

  • The Build Process: Preprocessor, Compiler, Linker, and Locator.

  • Preprocessor Directives: #include, macros, and conditional compilation.

  • STM32 Environment:

    • Tools: STM32CubeMX, VSCode, STM32CubeIDE.

    • HAL (Hardware Abstraction Layer): Abstraction of hardware peripherals (GPIO, Delay).

    • BSP (Board Support Package): Board-specific implementations.

2. Language Basics and Migration from C

Data Types and Safety

  • Standard C types vs. Fixed-width integers (uint8_t, int32_t, etc.).

  • Floating point types and precision.

  • Enumerations:

    • Unscoped enum (C-style).

    • Scoped enum class (Type-safe, strongly typed).

  • Type Conversion:

    • Implicit vs. Explicit conversion.

    • The auto keyword for automatic type deduction.

Structs and Classes

  • Transitioning from C Modules to C++ Classes.

  • Classes:

    • Attributes and Methods.

    • Access Modifiers: public, private, protected.

  • Separation of Declaration (Header) and Implementation (Source).

  • Name Mangling and using extern "C" for compatibility.

3. Object-Oriented Concepts and Optimization

Optimization Keywords

  • Constness: const variables and methods.

  • Inlining: inline functions for performance.

  • Compile-time Evaluation:

    • constexpr: Evaluated at compile-time if possible.

    • consteval (C++20): Immediate functions, strictly compile-time.

Object-Oriented Features

  • Inheritance: Public, Protected, and Private inheritance.

  • Relationships: Aggregation vs. Composition.

  • Namespaces: Named and Anonymous namespaces to avoid naming conflicts.

Casting

  • Risks of C-style casting.

  • C++ Cast Operators:

    • static_cast: Compile-time checked, safe conversions.

    • reinterpret_cast: Low-level reinterpretation (e.g., hardware addresses).

    • const_cast: Adding/removing constness.

    • dynamic_cast: Runtime checking (typically avoided in embedded due to overhead).

4. Templates and The Standard Template Library (STL)

Generic Programming

  • Function Templates: Generic algorithms for different data types.

  • Class Templates: Generic class structures.

  • Type Checking:

    • Traits: Compile-time type information (C++11).

    • Concepts: Constraints on template parameters (C++20).

The STL

  • Overview of Algorithms, Containers, Functions, and Iterators.

  • Efficiency of STL compared to custom implementations.

5. Memory Management

Memory Segments and Layout

  • Segments: .text (code), .data (initialized), .bss (uninitialized), Heap, Stack.

  • Memory Map of STM32 Microcontrollers.

  • Role of the MMU (Memory Management Unit) vs. No-MMU systems.

Dynamic Memory Allocation

  • Mechanisms: malloc/free (C) vs. new/delete (C++).

  • Issues in Real-Time Systems:

    • Heap Overflow and Stack Overflow.

    • Memory Leaks.

    • Fragmentation: External vs. Internal fragmentation.

    • Non-deterministic timing of allocation.

Custom Memory Management strategies

  • No Heap Strategy: Using only stack or static memory.

  • Static Allocation: Allocating once, never freeing.

  • Memory Pools:

    • Pre-allocating fixed-size blocks to avoid fragmentation.

    • Micro-management of memory heaps.

  • Custom Allocators:

    • Ring Allocators.

    • Stack-based allocators.

6. Containers and Iterators

Sequential Containers

  • std::array: Static size, stack-allocated, zero overhead.

  • std::vector: Dynamic size, heap-allocated, contiguous memory.

  • std::deque, std::list, std::forward_list.

Associative Containers

  • Ordered: std::map, std::set (Tree-based).

  • Unordered: Hash maps (typically avoid in embedded due to complexity).

Iterators

  • Types: Input, Output, Forward, Bidirectional, Random Access.

  • Methods: begin(), end(), cbegin(), cend().

7. Advanced C++ for Embedded

RAII (Resource Acquisition Is Initialization)

  • Principle: Binding resource lifecycle to object scope.

  • Use cases: Managing locks, files, and memory automatically.

  • Smart Pointers:

    • std::unique_ptr: Exclusive ownership, lightweight.

    • std::shared_ptr: Shared ownership, reference counting overhead.

    • std::weak_ptr: Non-owning reference.

Specialized Features

  • Placement New: Constructing objects at specific memory addresses (e.g., peripherals).

  • Custom Literals: User-defined units (e.g., 10.5_kg, 100_ms) for compile-time calculations.

  • std::variant: Type-safe union replacement (C++17).

  • String Handling: std::string vs. custom allocators for strings.