BareMetal-C

Bare Metal C: C99 Style Guide

Language: C (SDCC Compiler/C99 Standard)


0. Prerequisite

Read the C99 Coding Guidelines document first.

1. Core Philosophy

Moving from Python to C requires a shift in mindset. In C, you are managing the hardware directly. There is no automatic memory management, and safety features must be added by you, the programmer.


2. File Organization

#ifndef SENSOR_H
#define SENSOR_H

#include <stdint.h>
#include <stdbool.h>
#include "hardware_map.h"

// Prototypes go here

#endif

3. Formatting & Indentation

Bad (Hard to read/debug):

if (ready) { go = true; } else { go = false; }

Good:

if (ready) {
    go = true;
} else {
    go = false;
}

Bad (Dangling Else Risk):

if (a > 0)
    if (b > 0)
        c = 1;
else
    c = 0; // This 'else' attaches to the second 'if (b > 0)'!

Good: Correctly resolves the ambiguity by making the compiler’s default choice explicit.

if (a > 0) {
    if (b > 0) {
        c = 1;
    } else {
        c = 0;
    }
}

Use cascaded if-else:

When else is immediately followed by if, it is a good idea to not use { right after else, as this can make the code hard to read:

Good: easy to understand:

if (bitcoin >= 20) {
    class = PLATINUM;
} else if (bitcoin >= 10) {
    class = GOLD;
} else if (bitcoin >= 5) {
    class = SILVER;
} else {
    class = REGULAR;
}

Bad: indentation makes it hard to read:

if (bitcoin >= 20) {
    class = PLATINUM;
} else {
    if (bitcoin >= 10) {
        class = GOLD;
    } else {
        if (bitcoin >= 5) {
            class = SILVER;
        } else {
            class = REGULAR;
        }
    }
}

4. Data Types & Const Correctness

Do not use generic int or long. In embedded systems, we need to know exactly how many bits a number uses.

4.1 Strict Types

Always include and .

Type Description Use Case
uint8_t Unsigned 8-bit (0 to 255) Hardware registers, bytes, flags.
int8_t Signed 8-bit (-128 to 127) Small math values.
uint16_t Unsigned 16-bit (0 to 65,535) Counters, memory addresses.
bool Boolean (true/false) Logical checks.
void Empty/Nothing Functions returning nothing.

4.2 Const by Default

Variables should be immutable (const) by default. Only remove const if the variable must change (e.g., a counter or accumulator).

const uint8_t max_retries = 5;  // Good: This is a fixed setting
uint8_t current_retry = 0;      // Good: This changes in a loop

5. Naming Conventions


6. Functions & Scope


7. Python vs. C Cheat Sheet

Feature Python C99 Guideline
Blocks Indentation Curly Braces { } (Indentation is purely visual)
True/False True / False true / false (requires <stdbool.h>)
Variables Dynamic (x = 5) Static (const uint8_t x = 5;)
Strings “Hello” Array of chars (const char msg[] = "Hello";)
Printing print("Val:", x) uart_transmit_byte(x);
Main if __name__ == "__main__": void main(void) { ... }