源代码分析

2019-05-17 19:06

Pixhawk源码笔记一:APM代码基本结构

Pixhawk源码笔记一:APM代码基本结构

基础知识

详细参考:http://dev.ardupilot.com/wiki/learning-the-ardupilot-codebase/

第一部分:介绍

详细参考:http://dev.ardupilot.com/wiki/learning-ardupilot-introduction/ ArduPilot 代码分为5个主要部分,基本结构分类如下: vehicle directories AP_HAL libraries

tools directories

external support code

1、vehicle directories模型类型 当前共有4种模型:ArduPlane, ArduCopter, APMrover2 and AntennaTracker。都是.pde文件,就是为了兼容arduino平台,以后可能会放弃。

2、AP_HAL硬件抽象层

硬件抽象层,使得在不同硬件平台上的移植变得简单。

其中AP_HAL目录定义了一个通用的接口。其他的目录AP_HAL_XXX针对不同硬件平台进行详细的定义。例如AP_HAL_AVR目录对于AVR平台,AP_HAL_PX4对应PX4平台,AP_HAL_Linux对应Linux平台。

3、tools directories工具目录

主要提供支持。For examples, tools/autotest provides the autotest infrastructure behind the autotest.diydrones.com site and tools/Replay provides our log replay utility. 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

5、系统编译

针对不同的硬件板,编译可以采用“make TARGET”的形式。 make apm1 – the APM1 board make apm2 – the APM2 board make px4-v1 – the PX4v1

make px4-v2 – the Pixhawk

如果要移植到新的硬件,可以在mk/targets.mk文件中添加。 比如: make apm2-octa -j8 或者: make px4-v2 -j8

采用8通道并行编译方式,针对APM、Pixhawk硬件板(AVR、STM32),编译八旋翼代码。

第二部分: 学习sketch例程代码

http://dev.ardupilot.com/wiki/learning-ardupilot-the-example-sketches/ 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

例如,下面的编译方法,将在Pixhawk上安装AP_GPS例程sketch。 cd libraries/AP_GPS/examples/GPS_AUTO_test make px4-clean make px4-v2

make px4-v2-upload

正确理解sketch例程代码,我们以GPS_AUTO_test.pde代码为例(目录ardupilot\\libraries\\AP_GPS\\examples\\GPS_AUTO_test),主要几个特点: 1、 pde文件包含很多 includes; 2、 定义了 hal 引用声明; 3、 代码非常粗糙;

4、 setup() 和 loop()函数 1、include文件

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

Pixhawk源码笔记二:APM线程

Pixhawk源码笔记一:APM代码基本结构,参见: http://blog.sina.com.cn/s/blog_402c071e0102v59r.html

这里,我们对 APM 线程进行讲解。如有问题,可以交流30175224@qq.com。新浪@WalkAnt,转载本博客文章,请注明出处,以便更大范围的交流,谢谢。 第三部分 APM线程

详细参考:http://dev.ardupilot.com/wiki/learning-ardupilot-threading/

对于APM1、APM2硬件板,不支持多线程,所以只能通过简单的定时器加回调函数来实现。类似PX4和Linux硬件板支持Posix标准的多线程。线程一般是指基于多任务操作系统的并行任务,我们首先要明白的几个概念如下: 1、 定时回调

2、 HAL专属线程 3、 驱动专属线程

4、 APM驱动与板级驱动 5、 板级专属线程、任务

6、 AP_Scheduler任务调度系统 7、 信号灯(任务队列互锁用) 8、 lockless data structures

如果你对操作系统运行机制比较了解,那就很好理解了。 1、定时回调The timer callbacks

每个飞控平台都提供一个1kHz的定时器(见AP_HAL),通过“注册”一个定时器函数来获取1kHz定时功能。所有注册的定时器将被顺序调用。调用形式如下:

hal.scheduler->register_timer_process(AP_HAL_MEMBERPROC(&AP_Baro_MS5611::_update));

定时器优先级为181,高于主进程的180。上面代码是以MS5611气压计驱动为例,其中 AP_HAL_MEMBERPROC() 宏,主要作用是将一个C++成员函数包装起来,作为一个回调参数。其定义在AP_HAL_Namespace.h文件中,如下:

// macro to hide the details of AP_HAL::MemberProc

#define AP_HAL_MEMBERPROC(func) fastdelegate::MakeDelegate(this, func)

使用hal.scheduler->millis() and hal.scheduler->micros() 可以记录时间。

好了,你可以试着自己边一个简单的sketch,在setup()和loop()函数中练习一下1秒钟向USB终端输出一个时间或字符。 2、HAL专属线程

以PX4为例,HAL专属线程有:

1、 UART线程,用于读、写串行接口数据(包括USB); 2、 定时器线程,支持1kHz定时功能;

3、 IO线程,支持写microSD、EEPROM、FRAM等。 对于Pixhawk,请准备一条调试电缆,连接到nsh console(serial 5 端口),波特率57600。如果已经连接,试下”ps”命令,你会得到如下信息: PID PRI SCHD TYPE NP STATE NAME 0 0 FIFO TASK READY Idle Task()

1 192 FIFO KTHREAD WAITSIG hpwork() 2 50 FIFO KTHREAD WAITSIG lpwork() 3 100 FIFO TASK RUNNING init()

37 180 FIFO TASK WAITSEM AHRS_Test() AHRS线程 38 181 FIFO PTHREAD WAITSEM (20005400) 定时器线程

39 60 FIFO PTHREAD READY (20005400) UART线程 40 59 FIFO PTHREAD WAITSEM (20005400) IO线程 10 240 FIFO TASK WAITSEM px4io() 13 100 FIFO TASK WAITSEM fmuservo() 30 240 FIFO TASK WAITSEM uavcan()

上面的线程为定时器线程(优先级181),UART线程(60), IO线程(59),以及其他线程诸如:px4io, fmuservo, uavcan, lpwork, hpwork and idle tasks

线程的主要目的是在不干扰主进程的情况下,在后台处理一些低优先级任务。例如 AP_Terrain library,需要向microSD卡写地形文件,它的实现方式如下:

hal.scheduler->register_io_process(AP_HAL_MEMBERPROC(&AP_Terrain::io_timer));

注意:IO线程优先级59,相比定时器181优先级慢了很多。 3、Driver专属线程

没什么好说的,请参考英文原版,需要提的一点是,我们可以利用register_io_process() 和register_timer_process()来处理驱动的访问。 4、APM驱动与板级(原生)驱动

我们可以看到MPU6000驱动有两个版本:一个是APM版本,在libraries/AP_InertalSensor/AP_InertialSensor_MPU6000.cpp,另一个为原生代码版本,在PX4Firmware/src/drivers/mpu6000。

注意,对于Pixhawk,APM代码使用的是Pixhawk原生驱动,因为原生驱动已经做得很好了。libraries/AP_InertialSensor/AP_InertialSensor_PX4.cpp中可以查看详情。

在非PX4平台上,我们使用AP_InertialSensor_MPU6000.cpp驱动,在PX4平台上,我们就用PX4原生驱动AP_InertialSensor_PX4.cpp 5、板级专属线程、任务 在上面第2节“HAL专属线程”讲到”ps”命令显示的线程。很多都不是 AP_HAL_PX4 Schedule启动的线程,这些线程列举如下:

idle task – called when there is nothing else to run init – used to start up the system

px4io – handle the communication with the PX4IO co-processor

hpwork – PX4稍低优先级驱动线程。handle thread based PX4 drivers (mainly I2C drivers) lpwork –PX4非常低优先级驱动线程。handle thread based low priority work (eg. IO) fmuservo – AUX输出。handle talking to the auxillary PWM outputs on the FMU uavcan – handle the uavcan CANBUS protocol

这些任务的启动,由rc.APM脚本文件(ardupilot\\mk\\PX4\\ROMFS\\init.d\\rc.APM)指定。PX4启动时,会读取该文件。rc.APM属于nsh 类型脚本。作为练习,你可以修改rc.APM脚本文件,增加一些sleep和echo命令,那么当PX4启动时,通过debug console(也就是serial 5)可以显示出来。

更多内容,可以参考英文原版。 原生线程的启动代码如下:

hrt_call_every(&_call, 1000, _call_interval, (hrt_callout)&MPU6000::measure_trampoline, this);


源代码分析.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:基于导游讲解视角的景区旅游形象感知研究-以凤凰古城为例

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: