一.框架介绍
由于近期做关于无人机的项目,开始接触并研究Ardupilot源码,研究这套源码是一项很庞大的工程,通过查阅资料,做笔记记录下要点,以备复习与交流。
下图是pixhawkd的框架图:
ArduPilot 代码分为 5 个主要部分,基本结构分类如下:
- vehicle directories
- AP_HAL
- libraries
- tools directories
- external support code
以下是对这5个主要部分的简单介绍:
- vehicle directories 模型类型
模型目录是为每一个模型类型定义固件的最高级别的目录当前共有 4 种模型:ArduPlane, ArduCopter, APMrover2 ,AntennaTracker。都是.pde文件,为了兼容 arduino 平台 ,伴随着 .cpp 文件,每一个模型目录包含了一个* make.inc 文件,该文件列出了所依赖的库。Makefiles读取该文件并为编译创建-l和-L文件。 - AP_HAL 硬件抽象层
硬件抽象层,使得在不同硬件平台上的移植变得简单。 其中 AP_HAL 目录定义了一个通用的接口。其他的目录 AP_HAL_XXX 针对不同硬件平台进行详细的定义。例如 AP_HAL_AVR 目录对于 AVR 平台,AP_HAL_PX4 对应 PX4 平台,AP_HAL_Linux 对应 Linux
平台。 - tools directories 工具目录
主要提供支持。例如,tools/autotest 文件提供了自动检测的基础文件来自于autotest.diydrones.com网站,tools/Replay 提供日志重播的程序。 - external support code 外部支持代码
对于其他平台,需要外部支持代码。例如 Pixhawk、PX4 的支持代码如下:
- PX4NuttX – 板载实时系统。the core NuttX RTOS used on PX4 boards
- PX4Firmware – PX4 固件。the base PX4 middleware and drivers used on PX4 boards
- uavcan – 飞行器 CAN 通信协议。the uavcan CANBUS implementation used in ArduPilot
- mavlink – Mavlink 通信协议。the mavlink protocol and code generator
- 系统编译
Sketch 例程代码
在学习过程中,本人使用source insight 作为看源码的工具。 sketch,是指使用 .pde 文件编写的主程序。 找到以下sketches:
- libraries/AP_GPS/examples/GPS_AUTO_test
- libraries/AP_InertialSensor/examples/INS_generic
- libraries/AP_Compass/examples/AP_Compass_test
- libraries/AP_Baro/examples/BARO_generic
- libraries/AP_AHRS/examples/AHRS_Test
以GPS_AUTO_test.pde代码为例,sketch主要有以下几个主要特点:
1. pde文件包含很多includes,
pde 文件转变为 C++文件后,提供必要的库引用支持;
2. 定义了hal引用声明, 定义如下:
const AP_HAL::HAL& hal = AP_HAL_BOARD_DRIVER;// pixhawk 等价于 AP_HAL_PX4 该定义,方便访问硬件接口,比如 console 终端、定时器、I2C、SPI 接口等。实际的定义是在 HAL_PX4_Class.cpp 中定义,如下: const HAL_PX4 AP_HAL_PX4; 其中hal 是针对 AP_HAL_PX4 的引用,经常使用的方法如下:
- 终端字符输出。hal.console->printf() and hal.console->printf_P() to print strings (use the _P to use less memory on AVR)
- 获取当前运行时间。hal.scheduler->millis() and hal.scheduler->micros() to get the time since boot
- 延时。hal.scheduler->delay() and hal.scheduler->delay_microseconds() to sleep for a short time
- IO 输入输出。hal.gpio->pinMode(), hal.gpio->read() and hal.gpio->write() for accessing GPIO pins
- I2C 操作,hal.i2c
- SPI 操作,hal.spi
3. setup()和 loop()
每个 sketch 都有一个 setup()和 loop()函数。板子启动时,setup()被调用。这些调用都来自 HAL 代码中的 main()函数调用(HAL_PX4_Class.cpp 文件 main_loop())。setup()函数只调用一次,用于初始化所有 libraries。
Loop()循环被调用,执行主任务。
4. 、AP_HAL_MAIN()宏
每一个 sketch(.pde 文件)最底部,都有一个“AP_HAL_MAIN();”指令,它是一个 HAL 宏,用于定义一个 C++ main 函数,整个程序的入口。它真正的定义在 AP_HAL_PX4_Main.h 中。
#define AP_HAL_MAIN()
extern "C" __EXPORT int SKETCH_MAIN(int argc, char * const argv[]);
int SKETCH_MAIN(int argc, char * const argv[]) {
hal.init(argc, argv); \
return OK; \
}
作为程序的起点,在 AP_HAL_MAIN()里,就正式调用了 hal.init()初始化代码。 程序的执行过程就是:程序起点 AP_HAL_MAIN() hal.init() hal.main_loop() sketch 中的 setup()和 loop()。