3.1AP_HAL(APM的硬件抽象层)

前言

前段时间梳理了PX4IO以及PX4FMU的类,但是还是没真正上去梳理到硬件框架上去,这次直接开始梳理AP_HAL框架,从根本上去认识pixhawk在硬件框架上的实现;

namespace AP_HAL

在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();
}

class 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

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底层已经定义好了的驱动,只是封装的更好用.

你可能感兴趣的:(Ardupilot)