Architecture of NavHAL
NavHAL is structured as a statically configured abstraction layer that separates hardware interaction across three orthogonal domains: processor architecture, vendor-specific implementation, and board-level configuration. This separation enables fine-grained hardware control while maintaining portability and scalability.
At a high level, NavHAL consists of a unified interface layer built on top of an architecture-specific core, which is specialized through three components: core, vendor, and board. These components are selected at build time, ensuring that only the required implementation is included in the final binary.
The Interface Layer provides a consistent and hardware-agnostic API for peripherals such as GPIO, UART, I2C, SPI, and timers. It defines the contract used by upper layers without exposing implementation details.
The Core Layer contains architecture-specific logic and implements the functional behavior of peripherals. It translates API calls into hardware operations using definitions provided by the vendor and board layers.
The architecture is further decomposed into three domains:
Processor Layer: Implements architecture-level features such as startup routines, interrupt handling, and low-level execution primitives (e.g., Cortex-M4 support).
Vendor Layer: Defines microcontroller-specific details including register mappings, memory layouts, and peripheral structures. It enables direct access to hardware registers.
Board Layer: Provides board-level configuration such as pin mappings and default peripheral assignments, allowing application code to remain independent of physical layouts.
This separation allows independent evolution of each domain. Supporting a new board requires only board-level changes, while adapting to a different microcontroller primarily affects the vendor layer.
The abstraction is resolved at compile time through build configuration parameters (processor, vendor, and board). This eliminates unused components and reduces binary size.
To maintain efficiency, the design minimizes runtime indirection. Public APIs remain lightweight, while internal operations rely on inline functions and macros. As a result, most interactions map closely to direct register access.
NavHAL operates as a stateless access layer and does not enforce resource ownership or concurrency control. These responsibilities are delegated to the execution layer (e.g., VAIOS) when present, allowing NavHAL to remain lightweight and flexible.
Overall, the architecture combines structured abstraction with direct hardware access, enabling portability without sacrificing performance.