一、应用编程IAP
1.1 IAP
IAP是In Application Programming的首字符缩写。IAP是用户自己的程序在运行过程中对User Flash部分进行烧写,目的是为了在产品发布以后通过预留的接口对产品固件进行升级。
要想实现IAP,FLASH中需要存在2个程序:Bootloader和APP。设备启动时,首先运行Bootloader,判断是否需要升级。如果需要升级,则通过预留的接口,获取新固件,并烧写进flash;如果不需要升级,则直接跳到APP中运行,完成启动。
1.2 IAP在STM32中的应用
一片STM32芯片的Code(代码)区内一般只有一个用户程序。而IAP方案则是将代码区划分为两部分,两部分区域各存放一个程序,一个叫bootloader(引导加载程序),另一个较user application(用户应用程序)。bootloader在出厂时就固定下来了,在需要变更user application时只需要通过触发bootloader对user application的擦除和重新写入即可完成用户应用程序的更换。
STM32上电时,硬件会自动将0x0800 0000处的代码映射到0x0000 0000处,然后从0x0000 0000处开始运行,所以可以认为,STM32从0x0800 0000处开始运行。所以,需要把Bootloader内容烧写在0x0800 0000处。然后将APP内容烧写在FLASH剩余的区域。
在只有一个程序的情况下,程序的执行流程图如下图所示:
STM32有一个中断向量表,这个中断向量表存放在代码开始部分的后4个字节处(即0x08000004),代码开始的4个字节存放的是堆栈栈顶的地址,当发生中断后程序通过查找该表得到相应的中断服务程序入口地址,然后再跳到相应的中断服务程序中执行。上电后从0x08000004处取出复位中断向量的地址,然后跳转到复位中断程序的入口(标号①所示),执行结束后跳转到main函数中(标号②所示)。在执行main函数的过程中发生中断,则STM32强制将PC指针指回中断向量表处(标号③所示),从中断向量表中找到相应的中断函数入口地址,跳转到相应的中断服务函数(标号④所示),执行完中断函数后再返回到main函数中来(标号⑤所示)。
若在STM32中使用IAP方案,则内置的Flash分配情况大致如下图所示:
1.3 Ardupilot飞控IAP方案
1.3.1 Ardupilot飞控IAP方案,内置FLASH分配情况如下图所示:
1.3.2 PX4 Bootloader
源码:https://github.com/PX4/PX4-Bootloader.git
判断ardupilot飞控固件是否需要升级。如果需要升级,则通过预留的接口,获取新固件,并烧写进flash;如果不需要升级,则直接跳到ardupiot APP中运行,完成启动。
二、Ardupilot系统概述
2.1 Ardupilot基本框架
2.2 Ardupilot硬件抽象层
系统平台和硬件由class HAL提供接口抽象,四大系统软硬件平台分别进行了实现:HAL_ChibiOS,HAL_Linux,HAL_Empty, HAL_SITL,这样,将具体应用和底层系统硬件进行了解耦,具体应用只需操作HAL接口类提供的硬件抽象接口,而当应用部署到具体的系统硬件平台时,具体系统硬件平台将实现该抽象接口,从而多态到具体的硬件,如此,我们可以将应用部署到真实系统硬件平台,或者部署到模拟的系统硬件平台来实现应用仿真。
class HAL提供run的接口,用来启动应用,同时给系统平台提供封装了setup方法和loop方法的FunCallbacks接口类,系统平台实现run方法,并且在run方法中回调setup和loop。
应用的入口由AP_HAL_Main中的AP_HAL_MAIN系列的宏函数提供,其使用应用实现的setup和loop方法,多态到具体系统软硬件平台实现run方法,也就是上面第二点。
应用比如大的:AntennaTracker,APMRover2,ArduCopter, ArduPlane等类都提供setup和loop两个框架方法的实现,并调用AP_HAL_MAIN入口来启动,并且,小到一个传感器的测试用例比如AP_Compass_test也是如此;也就是应用层均使用面向接口编程,而这里的接口主要有以setup和loop为代表的启动运行接口,以及系统硬件平台的HAL接口。
2.3 回调函数
2.3.1、回调函数的定义
回调函数是指使用者自己定义一个函数,实现这个函数的程序内容,然后把这个函数(入口地址)作为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数。函数是你实现的,但由别人(或系统)的函数在运行时通过参数传递的方式调用,这就是所谓的回调函数。简单来说,当发生某种事件时,系统或其他函数将会自动调用你定义的一段函数。
2.3.2、回调函数的机制
(1)定义一个回调函数;
(2)提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;
(3)当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
2.3.3、回调函数的作用
可以把调用者与被调用者分开。调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数。(解耦)
2.3.4、回调函数的优点
(1)可以让实现方,根据回调方的多种形态进行不同的处理和操作。
(2)可以让实现方,根据自己的需要定制回调方的不同形态。
(3)可以将耗时的操作隐藏在回调方,不影响实现方其它信息的展示。
(4)让代码的逻辑更加集中,更加易读。
2.4 Ardupilot线程(Threading)
2.5 旋翼机代码框架
2.6 旋翼飞行模式
飞行模式大概可以分为四类:姿态控制模式(如:Stabilize)、姿态+高度控制模式(如:AltHOLD)、位置控制模式(如:Loiter)和全自动控制模式(如:AUTO、RTL、GUIDED等)。
结语
本文主要对ArduPilot系统框架做了简述,分别简要介绍了应用编程、ArduPilot基本框架和多旋翼的基本框架。由于篇幅有限,不能对各个模块进行更详细的介绍,后期有机会对其中的重要模块做一些详细的分析,比如:状态控制器和控制器等。
阿木实验室致力于为机器人研发提供开源软硬件工具和课程服务,让研发更高效!
- End -
技术发展的日新月异,阿木实验室将紧跟技术的脚步,不断把机器人行业最新的技术和硬件推荐给大家。看到经过我们培训的学员在技术上突飞猛进,是我们培训最大的价值。如果你在机器人行业,就请关注我们的公众号,我们将持续发布机器人行业最有价值的信息和技术。 |