ð Design Philosophy
These are the core design tenets that libhal and its associated libraries must
seek to achieve with every design choice, line written, and architecture change
made.
D.1 Multi Targeted
libhal and the libraries that extend it should work anywhere. So long as the
appropriate compiler or cross-compiler is used, the driver should behave as
intended. The exception is platform libraries, which are designated to
execute for a particular platform. Even so, platform libraries must be unit
testable on any host machine.
D.2 General
libhal interfaces should be general, meaning they do not include APIs or
configuration settings that are uncommon across most targets or specific to a
particular platform.
D.3 Safe & Reliable
libhal and its style guide aim to use patterns, techniques, and documentation
to reduce safety issues and improve reliability. libhal is designed with a
long-term roadmap toward functional safety certification (IEC 61508 / ISO
26262). Every design decision should consider whether it supports or obstructs
that goal.
D.4 Tested & Testable
libhal code should be unit tested and designed to be testable. We have future
plans to add hardware-in-the-loop testing as part of our testing infrastructure.
D.5 Fast Builds
libhal and its ecosystem provide prebuilt binaries for supported toolchain
configurations. Libraries should avoid dependencies that significantly increase
build times, and any new dependency must justify its compile-time cost.
D.6 Portable
libhal code must not depend on any OS or target-specific behavior. It is
designed to work on baremetal 32-bit MCUs, Linux, macOS, and Windows from the
same source. No platform-specific code may appear outside of platform libraries.
D.7 Explicit Over Implicit
libhal prefers explicit over implicit at every layer. Allocators are passed as parameters rather than taken from a global. Async context is a named parameter, not injected via thread-local storage. Dependencies are wired visibly. If something can be made a visible, traceable part of an API without a meaningful cost, it should be.
D.8 Memory Safety Through Ownership
Driver dependencies that outlive a function call must be held as hal::ptr<T>
which is a non-nullable, reference-counted smart pointer that tracks allocator
lifetime alongside the object. Raw references are valid only for dependencies
consumed within the current call and not retained. This model ensures that
no driver can outlive the resources it depends on.