Namespaces and Code Organization
Introduction
As firmware grows, names collide: init(), Status, Timer in every module. C used prefixes: hal_spi_init, drv_motor_start. C++ adds namespaces — group related names without verbose prefixes. You also organize headers (.hpp) and link with C drivers via extern "C".
Good structure keeps application code readable and stops HAL symbols from clashing with your robot Control class.
Namespaces — folders for names
1 2 3 4 5 6 7 8 9 10 11 12 | |
Use qualified names:
1 2 | |
In plain terms
A namespace is a surname for your functions. Motor alone might be ambiguous; drivers::Motor tells everyone which family you mean.
using — import with care
1 2 3 4 | |
Never using namespace std; in a header — it pollutes every file that includes you. In .cpp files, limited using for locals is fine.
Namespace + class together
| Tool | Best for |
|---|---|
| Namespace | Free functions, constants, enums |
| Class | State + behaviour (object) |
1 2 3 4 5 6 7 8 9 10 11 12 | |
Headers in C++
Convention:
| Extension | Typical use |
|---|---|
.h |
C headers, shared with C |
.hpp / .hh |
C++ headers |
Include guards (same as C):
1 2 3 4 5 6 7 8 | |
Or #pragma once (widely supported). One header per class or small module group — not one giant everything.hpp.
Linking C and C++
Most HAL is C. C++ name mangling would break the linker if you mixed blindly. Wrap C headers:
1 2 3 4 5 6 7 8 9 | |
extern "C" tells C++ compiler: use C linkage — symbol names match what hal_gpio.c exported.
Your main.cpp calls HAL_Init() without mangling errors.
Anonymous namespace — internal linkage
1 2 3 4 5 | |
Symbols visible only in this translation unit — like static functions in C. Use for file-local helpers in .cpp files.
Project layout example
1 2 3 4 5 6 7 8 9 | |
Dependency direction: app → drivers → hal. C++ application never includes vendor register headers directly if you can avoid it — keeps encapsulation real.
std namespace
Standard library lives in std:
1 2 3 4 5 | |
On embedded, many std facilities are absent or trimmed (<iostream>, full <vector>). See Embedded C++ subset. <cstdint>, <array>, <algorithm> on headers-only parts are common on capable MCUs.
Relevant topics
Starting points
- Wrap one vendor
hal_*.hwithextern "C"in a C++main.cpp. - Move one module into
namespace project_name { }— fix qualifiers. - Draw include graph: which headers pull in HAL vs drivers only.
- Remove
using namespace stdfrom any header in a sample repo.
Focus points
- Headers expose, sources implement — minimize
#includein headers (forward declare when possible). extern "C"at every C boundary.- No using namespace in headers — prevents surprise name clashes.
- Consistent naming —
drivers::,app::, or prefix style — pick one per repo.
Key points
- Namespaces group names and reduce prefix noise.
extern "C"links C++ code with C HAL and libraries.- Header organization and include guards keep builds fast and dependencies clear.
- Anonymous namespace hides file-local helpers — prefer over global
staticin C++.