Skip to main content

embedded-cpp14-misra

Use when writing, reviewing, or refactoring C/C++ firmware code in this repository (src/, lib/, test/) — creating or editing .h/.hpp/.cpp files, applying MISRA-oriented and defensive rules, Yoda conditions, single-exit/pathfinder control flow, mandatory Doxygen headers, and clang-format compliance. Covers the house C++14 style; not for Python build scripts, web assets, or docs.

Quellinformationen

Repository
BlueAndi/Pixelix
Letzte Quellaktivität
12. August 2026 um 15:47
Erkannte Sprache von SKILL.md
Englisch
Sterne
443
Forks
74

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
5 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
embedded-cpp14-misra
description
Use when writing, reviewing, or refactoring C/C++ firmware code in this repository (src/, lib/, test/) — creating or editing .h/.hpp/.cpp files, applying MISRA-oriented and defensive rules, Yoda conditions, single-exit/pathfinder control flow, mandatory Doxygen headers, and clang-format compliance. Covers the house C++14 style; not for Python build scripts, web assets, or docs.
# Embedded C++14 (MISRA-Oriented) House Style ## Overview Pixelix firmware is C++14 on ESP32 with hard constraints: limited RAM, no exceptions in practice, long uptimes, and dual-core FreeRTOS tasks. The house style optimizes for **deterministic, reviewable code** over brevity — explicit state, bounded loops, single exit, and a documented public API. Two style layers, both mandatory: 1. **Formatting** — mechanical, owned by `clang-format` (v18.1.3, [.clang-format](../../../.clang-format)). Never hand-tune against it; run it. 2. **Structure & safety** — the rules below. `clang-format` cannot check these; you must. CI enforces layer 1 on `src/` and `lib/` only: ```bash find src lib -iname '*.h' -o -iname '*.hpp' -o -iname '*.cpp' | xargs clang-format -i --dry-run -Werror ``` ## The Non-Negotiables Five rules distinguish this codebase from generic modern C++. Violating any of them will fail review. ### 1. Yoda conditions Constant or literal on the **left** of every equality/boolean comparison. Prevents `=`-for-`==` typos. ```cpp if (true == isReady) /* not: if (isReady) */ if (false == m_isRunning) /* not: if (!m_isRunning) */ if (nullptr == ptr) /* not: if (!ptr) */ if (0U == count) /* not: if (count == 0) */ ``` Relational comparisons (`<`, `>=`) keep natural order — Yoda applies to equality and explicit bool tests. ### 2. Single point of exit One `return` per function, at the end. Use a result variable, not early returns. ```cpp bool Foo::init() { bool isSuccessful = false; if (nullptr == m_buffer) { LOG_ERROR("No buffer."); } else if (true == m_isInitialized) { LOG_WARNING("Already initialized."); } else { m_isInitialized = true; isSuccessful = true; } return isSuccessful; } ``` An empty guard branch with an explanatory comment is idiomatic and preferred over inverting the whole body: ```cpp if (false == m_isInitialized) { /* Guard path: do not process before initialization. */ } else { ++m_counter; } ``` ### 3. Pathfinder rule One clear execution path per function. Guard-check invalid state first, keep nesting shallow (aim ≤ 3 levels), and split dense boolean chains into named helpers or named intermediate `bool` variables. If a reader cannot trace every path in one pass, decompose it. ### 4. Doxygen is mandatory Every file gets the MIT block plus `@file`, `@brief`, `@author`. Headers add `@addtogroup <GROUP>` / `@{` … `@}` around the content. Existing groups: `PLUGIN`, `GFX`, `UTILITIES`, `SETTINGS`, `SENSORS`, `HTTP_SERVICE`, `HAL`, `TOPIC_HANDLER_SERVICE`, `RTC`, `TEST`. Every public method needs a doc block with `@param[in]`/`@param[out]`/`@return` and any range, unit, ownership, or blocking behavior. Every member gets a trailing `/**< ... */`. ### 5. Section banners in fixed order Files are divided by 80-column banner comments. Order differs by file type — see the templates. Keep empty sections in place rather than deleting them. | `.h` | `.hpp` | `.cpp` | |------|--------|--------| | Includes | Compile Switches | Includes | | Compiler Switches | Includes | Compiler Switches | | Macros | Macros | Macros | | Types and Classes | Types and Classes | Types and classes | | Variables | Functions | Prototypes | | Functions | | Local Variables | | | | Public / Protected / Private Methods | | | | External / Local Functions | ## Safety Rules (MISRA-oriented) - Fixed-width types from `<stdint.h>` (`uint32_t`, `int16_t`); unsigned literals get a `U` suffix. - No implicit narrowing or signed/unsigned mixing — cast explicitly and say why if non-obvious. - No dynamic allocation unless justified in a comment; prefer fixed-size buffers and static/member storage. Heap fragmentation is a real failure mode on long-running devices. - Explicitly initialize every member in the constructor initializer list, in declaration order. - `const`-correct: `const` parameters, `const` methods, `const`/`constexpr` over macros. - No side effects inside conditions (no assignment, no `++`, no state-mutating calls in an `if`). - Bound every loop; bounds-check every index and every buffer write. - Validate all external input and every pointer parameter before use. - On failure, leave the object in a valid, consistent state and report status — never half-initialized. - Guard shared mutable state with `Mutex` / `MutexGuard` wherever a second task can reach it. Full detail and rationale → [references/coding-rules.md](references/coding-rules.md) ## Naming | Kind | Convention | Example | |------|-----------|---------| | Class / struct | PascalCase | `AudioDrv` | | Method / function | camelCase | `getSampleRate()` | | Member variable | `m_` + camelCase | `m_isInitialized` | | Local variable | camelCase | `isSuccessful` | | Constant / enum value | UPPER_SNAKE_CASE | `MAX_SLOTS` | | Macro | UPPER_SNAKE_CASE | `LOG_INFO` | | Include guard | `<FILE_NAME>_H` / `_HPP` | `AUDIO_DRV_H` | | Plugin class | must end in `Plugin` | `DateTimePlugin` | Boolean names read as predicates: `isRunning`, `hasData`, `isSuccessful`. ## Workflow **Creating a file** 1. Pick the type: `.h` for module and regular class headers, `.hpp` **only** for header-only / template code, `.cpp` for implementation. 2. Copy the matching template and replace the placeholders — `ClassName`, `CLASS_NAME`, `GROUP`, `@brief`, `@author`: - [assets/template.h](assets/template.h) - [assets/template.hpp](assets/template.hpp) - [assets/template.cpp](assets/template.cpp) 3. Place it beside its peers (`lib/<Module>/src/`, `src/<Subsystem>/`), and mirror the neighbors' patterns for anything the template doesn't cover. 4. Write guard checks and error paths before the happy path. 5. Document as you write, not after. **Editing an existing file** Match the surrounding file over this document where they disagree — local consistency wins. Keep the diff tight; do not reformat or restyle untouched code. **Before declaring done** ```bash clang-format --dry-run -Werror <file> # must be silent platformio run --environment esp32doit-devkit-v1-LED-32x8 platformio check --environment <env> --fail-on-defect=medium platformio test --environment test # if test/ is touched ``` Then walk the checklist: - [ ] Yoda conditions on all equality/bool tests - [ ] Exactly one `return` per function - [ ] Guard paths first; nesting shallow - [ ] Fixed-width types; no implicit conversions; `U` suffixes - [ ] All members initialized in declaration order - [ ] No unjustified dynamic allocation - [ ] Shared state mutex-protected - [ ] Doxygen on file, class, every public method, every member - [ ] Section banners present and correctly ordered - [ ] `clang-format` clean ## Common Mistakes | Mistake | House style | |---------|-------------| | `if (!ptr)` | `if (nullptr == ptr)` | | Early `return false;` in a guard | Set result variable, fall through to the single `return` | | `int` / `unsigned` for sizes and counts | `uint32_t`, `size_t`, `uint8_t` — fixed width | | `new` / `std::vector` growth in a hot or long-lived path | Fixed-size buffer, or a justifying comment | | Member assigned in the constructor body | Constructor initializer list, declaration order | | Public method with no doc block | `@brief`, `@param`, `@return` — always | | `#define MAX_LEN 10` | `static const uint32_t MAX_LEN = 10U;` | | Deleting an empty section banner | Keep it — the layout is the convention | | Reformatting a whole file while fixing three lines | Touch only what the change needs |
Auf GitHub ansehen