前段时间梳理了PX4IO以及PX4FMU的类,但是还是没真正上去梳理到硬件框架上去,这次直接开始梳理AP_HAL框架,从根本上去认识pixhawk在硬件框架上的实现;
在pixhawk里面对于硬件的驱动在使用上完全是依赖了nuttx的驱动层,所以在驱动的调用上也是沿用了nuttx的fs_ops的方式,但是通过源码可以发现的是,pixhawk对与硬件又进行了抽象例如之前抽象的Device以及派生出来的CDev,这些最终只是提出了一个device框架,来定义设备,以及派生出的字符设备;对于底层硬件抽象这是通过AP_HAL来完成:
【device】是对设备抽象的一个框架,使得设备代码更清晰、易维护;
【AP_HAL】是对硬件抽象的一个框架,目的在于适应多个硬件平台;
namespace AP_HAL {
/* 顶层的虚类 Hal. 最顶层的抽象类*/
class HAL;
/* 顶层驱动类 drivers. 抽象的各个接口驱动 */
class UARTDriver; //串口
class I2CDevice; //I2C
class I2CDeviceManager; //I2C
class Device;
/*SPI总线*/
class SPIDevice;
class SPIDeviceDriver;
class SPIDeviceManager;
/*外设抽象*/
class AnalogSource;
class AnalogIn;
class Storage;
class DigitalSource;
class GPIO;
class RCInput;
class RCOutput;
class Scheduler;
class Semaphore;
class OpticalFlow;
class Util;
/* Utility Classes */
class Print;
class Stream;
class BetterStream;
/* Typdefs for function pointers (Procedure, Member Procedure)
For member functions we use the FastDelegate delegates class
which allows us to encapculate a member function as a type
对于成员函数,我们使用FastDelegate代理类,它允许我们将一个成员函数封装为类型
*/
typedef void(*Proc)(void);
FUNCTOR_TYPEDEF(MemberProc, void);
/**
* Global names for all of the existing SPI devices on all platforms.
* 在所有平台上的存在的SPI设备名称
*/
enum SPIDeviceType {
// Devices using AP_HAL::SPIDevice abstraction
SPIDevice_Type = -1,
};
/* Must be implemented by the concrete HALs.
*必须有具体的HAL的实现
*调用AP_HAL::get_HAL()-->return static HAL_PX4 hal_px4
*class HAL_PX4 是公共继承了AP_HAL::HAL,所以绕了一圈最终的HAL就是AP_HAL::HAL,也就是上面所列举出 * 来的。
*/
const HAL& get_HAL();
}
在Pixhawk中的通过一个命名空间实现了对所有数据结构的抽象,下面挨个讨论;
对HAL来说在实现AP_HAL的时候就必须实现HAL,这里对应硬件(pixhawk)—>HAL_PX4_Class.h
class AP_HAL::HAL {
public:
HAL(AP_HAL::UARTDriver* _uartA, // console
AP_HAL::UARTDriver* _uartB, // 1st GPS
AP_HAL::UARTDriver* _uartC, // telem1
AP_HAL::UARTDriver* _uartD, // telem2
AP_HAL::UARTDriver* _uartE, // 2nd GPS
AP_HAL::UARTDriver* _uartF, // extra1
AP_HAL::I2CDeviceManager* _i2c_mgr,
AP_HAL::SPIDeviceManager* _spi,
AP_HAL::AnalogIn* _analogin,
AP_HAL::Storage* _storage,
AP_HAL::UARTDriver* _console,
AP_HAL::GPIO* _gpio,
AP_HAL::RCInput* _rcin,
AP_HAL::RCOutput* _rcout,
AP_HAL::Scheduler* _scheduler,
AP_HAL::Util* _util,
AP_HAL::OpticalFlow *_opticalflow)
:
uartA(_uartA),
uartB(_uartB),
uartC(_uartC),
uartD(_uartD),
uartE(_uartE),
uartF(_uartF),
i2c_mgr(_i2c_mgr),
spi(_spi),
analogin(_analogin),
storage(_storage),
console(_console),
gpio(_gpio),
rcin(_rcin),
rcout(_rcout),
scheduler(_scheduler),
util(_util),
opticalflow(_opticalflow)
{
AP_HAL::init();
}
// 定义回调纯虚函数
struct Callbacks {
virtual void setup() = 0;
virtual void loop() = 0;
};
// 实现setup_fun、loop_fun与私有函数指针_setup和_loop关联起来
struct FunCallbacks : public Callbacks {
FunCallbacks(void (*setup_fun)(void), void (*loop_fun)(void));
void setup() override { _setup(); }
void loop() override { _loop(); }
private:
void (*_setup)(void);
void (*_loop)(void);
};
//
virtual void run(int argc, char * const argv[], Callbacks* callbacks) const = 0;
AP_HAL::UARTDriver* uartA;
AP_HAL::UARTDriver* uartB;
AP_HAL::UARTDriver* uartC;
AP_HAL::UARTDriver* uartD;
AP_HAL::UARTDriver* uartE;
AP_HAL::UARTDriver* uartF;
AP_HAL::I2CDeviceManager* i2c_mgr;
AP_HAL::SPIDeviceManager* spi;
AP_HAL::AnalogIn* analogin;
AP_HAL::Storage* storage;
AP_HAL::UARTDriver* console;
AP_HAL::GPIO* gpio;
AP_HAL::RCInput* rcin;
AP_HAL::RCOutput* rcout;
AP_HAL::Scheduler* scheduler;
AP_HAL::Util *util;
AP_HAL::OpticalFlow *opticalflow;
};
(1)从结构上来看,HAL抽象了串口、i2c、spi、rcin、rcout、adc、storage…等设备及接口,在namespace AP_HAL中这几个抽象类是平行的,而在class HAL中定义了个各类的指针,方便建立与后面implement各个类建立关系;更多还是基于硬件平台的抽象了;
HAL构造函数中实现了建立关系;
(2)HAL 本身比价简单,仅仅是集合了所有类,我们关注具体对HAL实现的的HAL_PX4;
这里需要划重点,之前AP_HAL命名空间下的class 是一个纯粹的抽象,具体实现是要依附于硬件平台来的;
说直白一点,对pixhawk来说:
第一、定义namespace PX 包含类“大致”与AP_HAL相当
第二、定义各个class 对应公共继承AP_HAL下的class,例如HAL_PX4 继承AP_HAL::HAL;
路径对应上:
…/ardupilot/libraries/AP_HAL/AP_HAL_Namespace.h
…/ardupilot/libraries/AP_HAL_PX4/AP_HAL_PX4_Namespace.h
每个文件里面都包含命名空间里面各个类是实现,且都是一一对应过来的,PX支持多个硬件平台的原因也就是在这里了
从文件中,我们可以明显看到AP_HAL_AVR、AP_HAL_Empty、AP_HAL_FLYMAPLE、AP_HAL_LINUX、AP_HAL_PX4、AP_HAL_QURT…
对平台的支持可见一斑…
namespace PX4 {
class PX4Scheduler;
class PX4UARTDriver;
class PX4Storage;
class PX4RCInput;
class PX4RCOutput;
class PX4AnalogIn;
class PX4AnalogSource;
class PX4Util;
class PX4GPIO;
class PX4DigitalSource;
class NSHShellStream;
class PX4I2CDriver;
class PX4_I2C;
class Semaphore;
}
这里就是pixhwk平台下针对AP_HAL定义的namespace,查看每个class定义不难发现:
class PX4::PX4UARTDriver : public AP_HAL::UARTDriver;
class PX4::PX4Scheduler : public AP_HAL::Scheduler
…
都是继承了抽象AP_HAL下的抽象类
接下来就是每个类实现的了,…/ardupilot/libraries/AP_HAL_XXX该路径下存在各个不同硬件平台的实现;
其实这些class都是操作nuttx底层已经定义好了的驱动,只是封装的更好用.