一.框架介绍

由于近期做关于无人机的项目,开始接触并研究Ardupilot源码,研究这套源码是一项很庞大的工程,通过查阅资料,做笔记记录下要点,以备复习与交流。
下图是pixhawkd的框架图:

Arco design 源码解读_Arco design 源码解读


ArduPilot 代码分为 5 个主要部分,基本结构分类如下:

  • vehicle directories
  • AP_HAL
  • libraries
  • tools directories
  • external support code

以下是对这5个主要部分的简单介绍:

  1. vehicle directories 模型类型
    模型目录是为每一个模型类型定义固件的最高级别的目录当前共有 4 种模型:ArduPlane, ArduCopter, APMrover2 ,AntennaTracker。都是.pde文件,为了兼容 arduino 平台 ,伴随着 .cpp 文件,每一个模型目录包含了一个* make.inc 文件,该文件列出了所依赖的库。Makefiles读取该文件并为编译创建-l和-L文件。
  2. AP_HAL 硬件抽象层
    硬件抽象层,使得在不同硬件平台上的移植变得简单。 其中 AP_HAL 目录定义了一个通用的接口。其他的目录 AP_HAL_XXX 针对不同硬件平台进行详细的定义。例如 AP_HAL_AVR 目录对于 AVR 平台,AP_HAL_PX4 对应 PX4 平台,AP_HAL_Linux 对应 Linux
    平台。
  3. tools directories 工具目录
    主要提供支持。例如,tools/autotest 文件提供了自动检测的基础文件来自于autotest.diydrones.com网站,tools/Replay 提供日志重播的程序。
  4. 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
  1. 系统编译

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()。