The Hardware Abstraction Layer (HAL) is the boundary between ArduPilot’s vehicle and library code and the underlying operating system or bare-metal hardware. Every peripheral — serial ports, SPI buses, I2C devices, GPIO pins, RC inputs, RC outputs, storage — is accessed exclusively through HAL interfaces. This means the sameDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Ardupilot/ardupilot/llms.txt
Use this file to discover all available pages before exploring further.
ArduCopter/, ArduPlane/, and libraries/ code compiles and runs correctly on an STM32-based flight controller, a Linux single-board computer, an ESP32, and the SITL simulator without any platform-specific conditionals in shared code.
HAL interface overview
The top-level HAL object isAP_HAL::HAL, declared in libraries/AP_HAL/HAL.h. It holds pointers to every subsystem driver:
hal instance is declared as extern const AP_HAL::HAL& hal; and defined once per platform by the corresponding HAL implementation.
HAL implementations
AP_HAL_ChibiOS
Targets STM32 microcontrollers running ChibiOS. Used by Pixhawk, CubeBlack, and the majority of supported flight controllers.
AP_HAL_Linux
Targets Linux boards such as Raspberry Pi, NAVIO2, and BeagleBone. Uses standard POSIX APIs and
/dev device nodes.AP_HAL_ESP32
Targets the ESP32 SoC. Enables low-cost WiFi-connected autopilot builds.
AP_HAL_SITL
Used during Software-In-The-Loop simulation. Replaces hardware drivers with software models driven by the physics backend.
Using the HAL in library code
Any.cpp file that needs hardware access declares the global hal reference at file scope and then calls through it:
Never use platform-specific headers (e.g.,
<stm32f4xx.h>, <pigpio.h>) inside libraries/. All hardware access must go through the HAL interfaces. Platform-specific code belongs only inside the corresponding AP_HAL_* directory.Key HAL interfaces
UARTDriver — serial ports
UARTDriver — serial ports
Access serial ports by their
SERIALn index (0–9). Port 0 is the console/USB; ports 1 and 2 are the primary telemetry links; ports 3 and 4 are typically GPS.GPIO — general-purpose I/O
GPIO — general-purpose I/O
The Constants:
hal.gpio interface provides pinMode(), read(), write(), and toggle().HAL_GPIO_INPUT = 0, HAL_GPIO_OUTPUT = 1, HAL_GPIO_ALT = 2.Scheduler — timing and tasks
Scheduler — timing and tasks
AP_HAL::millis() and AP_HAL::micros() for non-blocking time checks instead of delay() inside hot loops.I2C — I2C device manager
I2C — I2C device manager
Storage — parameter/EEPROM storage
Storage — parameter/EEPROM storage
RCInput / RCOutput
RCInput / RCOutput
The AP_HAL_MAIN macro
Every ArduPilot binary defines its entry point with theAP_HAL_MAIN() macro from libraries/AP_HAL/AP_HAL_Main.h. This macro wraps setup() and loop() in a HAL::FunCallbacks object and calls hal.run(), which is implemented differently on each platform:
main(); in SITL it hooks into the simulation event loop.
Time functions
Always use the HAL time functions instead of platform-specific calls:libraries/AP_HAL/system.h and resolve to the correct platform implementation at link time.
Design rules
- No platform headers in shared libraries. All hardware access must go through
hal.*interfaces. - No direct
printforcout. Usehal.console->printf()for debug output during development, orGCS_SEND_TEXT()for operator-visible messages. - No
std::chronoor POSIX time. UseAP_HAL::millis()/AP_HAL::micros(). - Use
CLASS_NO_COPY(). Most HAL objects and library classes should be non-copyable singletons. - Feature guards. Wrap optional hardware features in
#if AP_<FEATURE>_ENABLEDto allow builds on resource-constrained boards.