|
PER Firmware
|
Irving Wang (irvin.nosp@m.gw@p.nosp@m.urdue.nosp@m..edu)
This document defines the general coding style and rules for PER-owned projects. Most of these rules are C-specific but the essence of the rules can still be applied to other languages.
The goal is to maintain a consistent and easily maintainable codebase. Following these rules reduces opportunities for hidden bugs and makes the code more readable and reviewable for others.
Additionally, the compiler standard for firmware is set to C23, enabling several important modern features.
bool, nullptr as standard keywordsconstexpr for compile-time constantsstatic_assert for compile-time assertionsAvoid nesting where possible
malloc(), this will open the risk for memory fragmentationenum, static constexpr, or macrostatic constexpr over macros for inherent type safetyVariable names
snake_caseg_i or jFunction names
snake_caseSCREAMING_SNAKE_CASEWrap values with parenthesis to prevent expansion edge cases
```c // Example pulled from firmware/PR(#147)
// bad #define ABS(x) ((x) < 0 ? (-1 * x) : x) // good #define ABS(x) ((x) < 0 ? (-1 * (x)) : (x)) ```
Don’t use brace-less control statements
Allowed data types
floatcharbool (standard keyword in C23)<stdint.h>Always initialize variables with a value
c type_t g_global_struct = {0}; uint8_t g_global_val = 0;
struct declarations
typedef and suffix your new type with _t```c // bad, 24 bytes of padding typedef struct { uint16_t small_num; uint32_t medium_num; uint64_t big_num; uint16_t small_num2; } bad_struct_t
// good, 0 bytes of padding typedef struct { uint64_t big_num; uint32_t medium_num; uint16_t small_num; uint16_t small_num2; } good_struct_t; ```
enum declaration
typedef and suffix your new type with _tstructc // example enum typedef enum : uint8_t { FAULT_STATE_CLEAR = 0, FAULT_STATE_PENDING = 1, FAULT_STATE_LATCHED = 2, FAULT_STATE_RECOVERING = 3 } fault_state_t;
Check null pointers before dereferencing
```c // bad void pass_by_reference(uint16_t *ptr) { *ptr = 10 }
// good void pass_by_reference(uint16_t *ptr) { if (ptr == nullptr) { return; // or return error code } *ptr = 10 } ```
Use apostrophes to format large numbers (C23) ```c // bad static constexpr uint32_t TargetCoreClockrateHz = 16000000;
// good static constexpr uint32_t TargetCoreClockrateHz = 16'000'000; ```
clang-format -i file.c