源代码解析.docx

上传人:b****8 文档编号:9686215 上传时间:2023-02-05 格式:DOCX 页数:45 大小:43.45KB
下载 相关 举报
源代码解析.docx_第1页
第1页 / 共45页
源代码解析.docx_第2页
第2页 / 共45页
源代码解析.docx_第3页
第3页 / 共45页
源代码解析.docx_第4页
第4页 / 共45页
源代码解析.docx_第5页
第5页 / 共45页
点击查看更多>>
下载资源
资源描述

源代码解析.docx

《源代码解析.docx》由会员分享,可在线阅读,更多相关《源代码解析.docx(45页珍藏版)》请在冰豆网上搜索。

源代码解析.docx

源代码解析

Pixhawk源码笔记一:

APM代码基本结构

 

Pixhawk源码笔记一:

APM代码基本结构

基础知识

详细参考:

第一部分:

介绍

详细参考:

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

vehicledirectories

AP_HAL

libraries

toolsdirectories

externalsupportcode

1、vehicledirectories模型类型

当前共有4种模型:

ArduPlane,ArduCopter,APMrover2andAntennaTracker。

都是.pde文件,就是为了兼容arduino平台,以后可能会放弃。

2、AP_HAL硬件抽象层

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

其中AP_HAL目录定义了一个通用的接口。

其他的目录AP_HAL_XXX针对不同硬件平台进行详细的定义。

例如AP_HAL_AVR目录对于AVR平台,AP_HAL_PX4对应PX4平台,AP_HAL_Linux对应Linux平台。

3、toolsdirectories工具目录

主要提供支持。

Forexamples,tools/autotestprovidestheautotestinfrastructurebehindthesiteandtools/Replayprovidesourlogreplayutility.

4、externalsupportcode外部支持代码

对于其他平台,需要外部支持代码。

例如Pixhawk、PX4的支持代码如下:

PX4NuttX–板载实时系统。

thecoreNuttXRTOSusedonPX4boards

PX4Firmware–PX4固件。

thebasePX4middlewareanddriversusedonPX4boards

uavcan–飞行器CAN通信协议。

theuavcanCANBUSimplementationusedinArduPilot

mavlink–Mavlink通信协议。

themavlinkprotocolandcodegenerator

5、系统编译

针对不同的硬件板,编译可以采用“makeTARGET”的形式。

makeapm1–theAPM1board

makeapm2–theAPM2board

makepx4-v1–thePX4v1

makepx4-v2–thePixhawk

如果要移植到新的硬件,可以在mk/targets.mk文件中添加。

比如:

makeapm2-octa-j8

或者:

makepx4-v2-j8

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

第二部分:

学习sketch例程代码

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。

cdlibraries/AP_GPS/examples/GPS_AUTO_test

makepx4-clean

makepx4-v2

makepx4-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引用声明

定义如下:

constAP_HAL:

:

HAL&hal=AP_HAL_BOARD_DRIVER;//pixhawk等价于AP_HAL_PX4

该定义,方便访问硬件接口,比如console终端、定时器、I2C、SPI接口等。

实际的定义是在HAL_PX4_Class.cpp中定义,如下:

constHAL_PX4AP_HAL_PX4;

hal是针对AP_HAL_PX4的引用。

经常使用的方法如下:

终端字符输出。

hal.console->printf()andhal.console->printf_P()toprintstrings(usethe_PtouselessmemoryonAVR)

获取当前运行时间。

hal.scheduler->millis()andhal.scheduler->micros()togetthetimesinceboot

延时。

hal.scheduler->delay()andhal.scheduler->delay_microseconds()tosleepforashorttime

IO输入输出。

hal.gpio->pinMode(),hal.gpio->read()andhal.gpio->write()foraccessingGPIOpins

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中。

#defineAP_HAL_MAIN()\

extern"C"__EXPORTintSKETCH_MAIN(intargc,char*constargv[]);\

intSKETCH_MAIN(intargc,char*constargv[]){\

hal.init(argc,argv);\

returnOK;\

}

作为程序的起点,在AP_HAL_MAIN()里,就正式调用了hal.init()初始化代码。

程序的执行过程就是:

程序起点AP_HAL_MAIN()àhal.init()àhal.main_loop()àsketch中的setup()和loop()。

Pixhawk源码笔记二:

APM线程

Pixhawk源码笔记一:

APM代码基本结构,参见:

        

        这里,我们对APM线程进行讲解。

如有问题,可以交流30175224@。

新浪@WalkAnt,转载本博客文章,请注明出处,以便更大范围的交流,谢谢。

第三部分 APM线程

        详细参考:

        对于APM1、APM2硬件板,不支持多线程,所以只能通过简单的定时器加回调函数来实现。

类似PX4和Linux硬件板支持Posix标准的多线程。

线程一般是指基于多任务操作系统的并行任务,我们首先要明白的几个概念如下:

        1、定时回调

        2、HAL专属线程

        3、驱动专属线程

        4、APM驱动与板级驱动

        5、板级专属线程、任务

        6、AP_Scheduler任务调度系统

        7、信号灯(任务队列互锁用)

        8、locklessdatastructures

        如果你对操作系统运行机制比较了解,那就很好理解了。

1、定时回调Thetimercallbacks

        每个飞控平台都提供一个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文件中,如下:

 

        //macrotohidethedetailsofAP_HAL:

:

MemberProc

        #define AP_HAL_MEMBERPROC(func)fastdelegate:

:

MakeDelegate(this,func)

 

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

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

2、HAL专属线程

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

        1、UART线程,用于读、写串行接口数据(包括USB);

        2、定时器线程,支持1kHz定时功能;

        3、IO线程,支持写microSD、EEPROM、FRAM等。

        对于Pixhawk,请准备一条调试电缆,连接到nshconsole(serial5端口),波特率57600。

如果已经连接,试下”ps”命令,你会得到如下信息:

        PIDPRISCHDTYPENPSTATENAME

        00FIFOTASKREADYIdleTask()

        1192FIFOKTHREADWAITSIGhpwork()

        250FIFOKTHREADWAITSIGlpwork()

        3100FIFOTASKRUNNINGinit()

        37180FIFOTASKWAITSEMAHRS_Test()                                AHRS线程

        38181FIFOPTHREADWAITSEM(20005400)         定时器线程

        3960FIFOPTHREADREADY(20005400)                UART线程

        4059FIFOPTHREADWAITSEM(20005400)          IO线程

        10240FIFOTASKWAITSEMpx4io()

        13100FIFOTASKWAITSEMfmuservo()

        30240FIFOTASKWAITSEMuavcan()

        上面的线程为定时器线程(优先级181),UART线程(60),IO线程(59),以及其他线程诸如:

px4io,fmuservo,uavcan,lpwork,hpworkandidletasks

        线程的主要目的是在不干扰主进程的情况下,在后台处理一些低优先级任务。

例如AP_Terrainlibrary,需要向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_PX4Schedule启动的线程,这些线程列举如下:

 idletask–calledwhenthereisnothingelsetorun

 init–usedtostartupthesystem

 px4io–handlethecommunicationwiththePX4IOco-processor

 hpwork–PX4稍低优先级驱动线程。

handlethreadbasedPX4drivers(mainlyI2Cdrivers)

 lpwork–PX4非常低优先级驱动线程。

handlethreadbasedlowprioritywork(eg.IO)

 fmuservo–AUX输出。

handletalkingtotheauxillaryPWMoutputsontheFMU

 uavcan–handletheuavcanCANBUSprotocol

        这些任务的启动,由rc.APM脚本文件(ardupilot\mk\PX4\ROMFS\init.d\rc.APM)指定。

PX4启动时,会读取该文件。

rc.APM属于nsh类型脚本。

作为练习,你可以修改rc.APM脚本文件,增加一些sleep和echo命令,那么当PX4启动时,通过debugconsole(也就是serial5)可以显示出来。

        更多内容,可以参考英文原版。

        原生线程的启动代码如下:

 

        hrt_call_every(&_call,1000,_call_interval,(hrt_callout)&MPU6000:

:

measure_trampoline,this);

 

        等同于AP_HAL中的hal.scheduler->register_timer_process()。

上述代码的意思是,HRT(highresolutiontimer)高精度定时器,以1000微妙的周期调用MPU6000:

:

measure_trampoline函数。

这些操作是禁止中断的,最多占用数十微妙的时间。

        上面的优先级非常高。

下面的方法,是稍低优先级。

 

        work_queue(HPWORK,&_work,(worker_t)&HMC5883:

:

cycle_trampoline,this,1);

 

        用于处理I2C设备。

大概花几百微妙的操作时间。

是可以被中断的任务。

如果是最低优先级,那么参数改为LPWORK,这样的任务一般需要花费更长的时间。

6、AP_Scheduler任务调度系统

        用于飞行器主线程,提供了简单的机制控制每个操作花费了多少时间。

例如:

1、等待一个新IMU采样;2、在每一个IMU采样周期之间调用一系列其他任务。

        每一个飞行器都有一个AP_Scheduler:

:

Tasktable任务列表,参考代码(ardupilot\libraries\AP_Scheduler\ Scheduler_test.pde )类似如下:

                staticconstAP_Scheduler:

:

Taskscheduler_tasks[]PROGMEM={

                {ins_update,1,1000},

                {one_hz_print,50,1000},

                {five_second_call,250,1800},

                };

        结构体第1列,循环调用的任务函数。

第2列,调用频率(也叫tick,一个tick,就是一个最小时间单元,pixhawk为2.5ms)。

第3列为最大可能占用的操作时间,scheduler.run()会传递当前可用的时间(微秒),如果时间不够,那么这个任务就pass掉了,不执行。

        注意,AP_Scheduler:

:

Tasktable列表必须具备以下条件:

        1、他们不能被阻塞。

        2、在飞行时,他们不能调用sleepfunction

        3、他们必须有可预估的最坏的运行时间。

        你可以修改Scheduler_test.pde,加入自己的代码来读取气压计、罗盘、GPS、更新AHRS输出roll/pitch。

7、信号灯

        有3种方法可以避免多线程访问冲突:

1、信号灯;2、locklessdata;3、PX4ORB。

        例如:

I2C驱动可以通过信号灯,确保同一时间,只有一个I2C设备被使用。

可以查看ardupilot\libraries\AP_Compass\AP_Compass_HMC5843.cpp了解:

        获得信号灯:

_i2c_sem->take

(1);

        释放信号灯:

_i2c_sem->give();

8、LocklessDataStructures

        LocklessDataStructures比信号灯要方便,例子见:

 the_shared_datastructureinlibraries/AP_InertialSensor/AP_InertialSensor_MPU9250.cpp

 theringbuffersusedinnumerousplaces.Agoodexampleislibraries/DataFlash/DataFlash_File.cpp

        Goandhavealookatthesetwoexamples,andprovetoyourselfthattheyaresafeforconcurrentaccess.ForDataFlash_Filelookattheuseofthe_writebuf_headand_writebuf_tailvariables.

9、PX4ORB

        ORB(ObjectRequestBroker)是PX4的互斥机制。

        另外两种PX4驱动通信机制,列举如下:

 ioctl calls(seetheexamplesinAP_HAL_PX4/RCOutput.cpp)

 /dev/xxx read/write calls(see_timer_tickinAP_HAL_PX4/RCOutput.cpp)

        想要学习Pixhawk源码的朋友有福了,后边我会陆续的将Pixhawk的源码学习笔记整理出来分享给大家。

敬请关注:

新浪微博@WalkAnt,3017224@。

欢迎交流。

Pixhawk源码笔记三:

串行接口UART和Console

这里,我们对APMUARTConsole接口进行讲解。

如有问题,可以交流30175224@。

新浪@WalkAnt,转载本博客文章,请注明出处,以便更大范围的交流,谢谢。

第四部分 串行接口UART和Console

        详细参考:

        UART很重要,用于调试输出,数传、GPS模块等。

1、5个UART

        目前共定义了5个UART,他们的用途分别是:

   uartA–串行终端,通常是MicroUSB接口,运行MAVLink协议。

   uartB–GPS1模块。

   uartC–主数传接口,也就是Pixhawktelem1接口。

   uartD–次数传接口,也就是telem2接口。

   uartE–GPS2模块。

        有些UART具备双重角色,比如通过修改SERIAL2_PROTOCOL参数

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 艺术创意

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1