AP_HAL 分析, 以pixhawk-fmuv2为硬件平台,ChibiOS为底层操作系统:

2024-06-12 14:18

本文主要是介绍AP_HAL 分析, 以pixhawk-fmuv2为硬件平台,ChibiOS为底层操作系统:,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. class AP_HAL::AP_HAL,该接口类聚合了所有提供给应用层的硬件接口

class AP_HAL::HAL {
public:HAL(AP_HAL::UARTDriver* _uartA, // consoleAP_HAL::UARTDriver* _uartB, // 1st GPSAP_HAL::UARTDriver* _uartC, // telem1AP_HAL::UARTDriver* _uartD, // telem2AP_HAL::UARTDriver* _uartE, // 2nd GPSAP_HAL::UARTDriver* _uartF, // extra1AP_HAL::UARTDriver* _uartG, // extra2AP_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,AP_HAL::Flash *_flash,
#if HAL_WITH_UAVCANAP_HAL::CANManager* _can_mgr[MAX_NUMBER_OF_CAN_DRIVERS])
#elseAP_HAL::CANManager** _can_mgr)
#endif:uartA(_uartA),uartB(_uartB),uartC(_uartC),uartD(_uartD),uartE(_uartE),uartF(_uartF),uartG(_uartG),i2c_mgr(_i2c_mgr),spi(_spi),analogin(_analogin),storage(_storage),console(_console),gpio(_gpio),rcin(_rcin),rcout(_rcout),scheduler(_scheduler),util(_util),opticalflow(_opticalflow),flash(_flash){
#if HAL_WITH_UAVCANif (_can_mgr == nullptr) {for (uint8_t i = 0; i < MAX_NUMBER_OF_CAN_DRIVERS; i++)can_mgr[i] = nullptr;} else {for (uint8_t i = 0; i < MAX_NUMBER_OF_CAN_DRIVERS; i++)can_mgr[i] = _can_mgr[i];}
#endifAP_HAL::init();}struct Callbacks {virtual void setup() = 0;virtual void loop() = 0;};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::UARTDriver* uartG;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;AP_HAL::Flash       *flash;
#if HAL_WITH_UAVCANAP_HAL::CANManager* can_mgr[MAX_NUMBER_OF_CAN_DRIVERS];
#elseAP_HAL::CANManager** can_mgr;
#endif
};

继承关系
AP_HAL继承关系

我们看到ardupilot中有四大系统平台(这里的系统平台指的是基于硬件平台的操作系统和底层驱动的集合,系统平台也可以是虚拟的)实现了该接口类,我们这里分析HAL_ChibiOS

2. class HAL_ChibiOS 实现了AP_HAL::HAL接口类

class HAL_ChibiOS : public AP_HAL::HAL {
public:HAL_ChibiOS();void run(int argc, char* const* argv, Callbacks* callbacks) const override;
};
在实现文件中我们看到:
static HAL_UARTA_DRIVER; ///< #define HAL_UARTA_DRIVER ChibiOS::UARTDriver uartADriver(0)
static HAL_UARTB_DRIVER; ///< #define HAL_UARTB_DRIVER ChibiOS::UARTDriver uartBDriver(1)
static HAL_UARTC_DRIVER; ///< #define HAL_UARTC_DRIVER ChibiOS::UARTDriver uartCDriver(2)
static HAL_UARTD_DRIVER; ///< #define HAL_UARTD_DRIVER ChibiOS::UARTDriver uartDDriver(3)
static HAL_UARTE_DRIVER; ///< #define HAL_UARTE_DRIVER ChibiOS::UARTDriver uartEDriver(4)
static HAL_UARTF_DRIVER; ///< #define HAL_UARTF_DRIVER ChibiOS::UARTDriver uartFDriver(5)
static HAL_UARTG_DRIVER; ///< #define HAL_UARTG_DRIVER Empty::UARTDriver uartGDriver
///< 前面这些宏定义在build/fmuv2/hwdef.h头文件中, 该头文件在编译时由python脚本从hwdef.dat文件中解析然后生成
///< 我们这里的硬件平台的硬件定义文件位于:ardupilot/libraries/AP_HAL_ChibiOS/hwdef/fmuv2/hwdef.dat
static ChibiOS::I2CDeviceManager i2cDeviceManager;
static ChibiOS::SPIDeviceManager spiDeviceManager;
static ChibiOS::AnalogIn analogIn;
static ChibiOS::Storage storageDriver;
static ChibiOS::GPIO gpioDriver;
static ChibiOS::RCInput rcinDriver;
static ChibiOS::RCOutput rcoutDriver;
static ChibiOS::Scheduler schedulerInstance;
static ChibiOS::Util utilInstance;
static Empty::OpticalFlow opticalFlowDriver;
static ChibiOS::Flash flashDriver;

在构造函数中,这些对象会被传递进去:

HAL_ChibiOS::HAL_ChibiOS() :AP_HAL::HAL(&uartADriver,&uartBDriver,&uartCDriver,&uartDDriver,&uartEDriver,&uartFDriver,&uartGDriver,&i2cDeviceManager,&spiDeviceManager,&analogIn,&storageDriver,&uartADriver,&gpioDriver,&rcinDriver,&rcoutDriver,&schedulerInstance,&utilInstance,&opticalFlowDriver,&flashDriver,nullptr)
{}

3. 我们进入到具体的uartADriver实例对应的类ChibiOS::UARTDriver中,其属于AP_HAL::UARTDriver接口的实现

继承关系
可以看到,四大系统平台都分别实现了AP_HAL::UARTDriver接口
协作图

class ChibiOS::UARTDriver : public AP_HAL::UARTDriver { ///< 
public:UARTDriver(uint8_t serial_num);void begin(uint32_t b) override;void begin(uint32_t b, uint16_t rxS, uint16_t txS) override;void end() override;void flush() override;bool is_initialized() override;void set_blocking_writes(bool blocking) override;bool tx_pending() override;uint32_t available() override;uint32_t txspace() override;int16_t read() override;int16_t read_locked(uint32_t key) override;void _timer_tick(void) override;size_t write(uint8_t c) override;size_t write(const uint8_t *buffer, size_t size) override;// lock a port for exclusive use. Use a key of 0 to unlockbool lock_port(uint32_t write_key, uint32_t read_key) override;// control optional featuresbool set_options(uint8_t options) override;// write to a locked port. If port is locked and key is not correct then 0 is returned// and write is discardedsize_t write_locked(const uint8_t *buffer, size_t size, uint32_t key) override;struct SerialDef {BaseSequentialStream* serial;bool is_usb;bool dma_rx;uint8_t dma_rx_stream_id;uint32_t dma_rx_channel_id;bool dma_tx;uint8_t dma_tx_stream_id;uint32_t dma_tx_channel_id; ioline_t rts_line;int8_t rxinv_gpio;uint8_t rxinv_polarity;int8_t txinv_gpio;uint8_t txinv_polarity;uint8_t get_index(void) const {return uint8_t(this - &_serial_tab[0]);}};bool wait_timeout(uint16_t n, uint32_t timeout_ms) override;void set_flow_control(enum flow_control flow_control) override;enum flow_control get_flow_control(void) override { return _flow_control; }// allow for low latency writesbool set_unbuffered_writes(bool on) override;void configure_parity(uint8_t v) override;void set_stop_bits(int n) override;/*return timestamp estimate in microseconds for when the start ofa nbytes packet arrived on the uart. This should be treated as atime constraint, not an exact time. It is guaranteed that thepacket did not start being received after this time, but itcould have been in a system buffer before the returned time.This takes account of the baudrate of the link. For transportsthat have no baudrate (such as USB) the time estimate may beless accurate.A return value of zero means the HAL does not support this API*/uint64_t receive_time_constraint_us(uint16_t nbytes) override;uint32_t bw_in_kilobytes_per_second() const override {if (sdef.is_usb) {return 200;}return _baudrate/(9*1024);}private:bool tx_bounce_buf_ready;const SerialDef &sdef;// thread used for all UARTsstatic thread_t *uart_thread_ctx;// table to find UARTDrivers from serial number, used for event handlingstatic UARTDriver *uart_drivers[UART_MAX_DRIVERS];// index into uart_drivers tableuint8_t serial_num;// key for a locked portuint32_t lock_write_key;uint32_t lock_read_key;uint32_t _baudrate;uint16_t tx_len;
#if HAL_USE_SERIAL == TRUESerialConfig sercfg;
#endifconst thread_t* _uart_owner_thd;struct {// thread waiting for datathread_t *thread_ctx;// number of bytes neededuint16_t n;} _wait;// we use in-task ring buffers to reduce the system call cost// of ::read() and ::write() in the main loop,使用ringbuffer降低mainloop中read/write系统调用开销uint8_t *rx_bounce_buf;///< 接收弹性bufferuint8_t *tx_bounce_buf;///< 发送弹性bufferByteBuffer _readbuf{0}; ///< 接收ringbufferByteBuffer _writebuf{0};///< 发送ringbufferSemaphore _write_mutex;const stm32_dma_stream_t* rxdma; ///< 接收dmaconst stm32_dma_stream_t* txdma; ///< 发送dmavirtual_timer_t tx_timeout;    bool _in_timer;bool _blocking_writes;bool _initialised;bool _device_initialised;bool _lock_rx_in_timer_tick = false;Shared_DMA *dma_handle;static const SerialDef _serial_tab[];// timestamp for receiving data on the UART, avoiding a lockuint64_t _receive_timestamp[2];uint8_t _receive_timestamp_idx;// handling of flow controlenum flow_control _flow_control = FLOW_CONTROL_DISABLE;bool _rts_is_active;uint32_t _last_write_completed_us;uint32_t _first_write_started_us;uint32_t _total_written;// we remember cr2 and cr2 options from set_options to apply on sdStart()uint32_t _cr3_options;uint32_t _cr2_options;// half duplex control. After writing we throw away bytes for 4 byte widths to// prevent reading our own bytes backbool half_duplex;uint32_t hd_read_delay_us;uint32_t hd_write_us;void half_duplex_setup_delay(uint16_t len);// set to true for unbuffered writes (low latency writes)bool unbuffered_writes;static void rx_irq_cb(void* sd);static void rxbuff_full_irq(void* self, uint32_t flags);static void tx_complete(void* self, uint32_t flags);static void handle_tx_timeout(void *arg);void dma_tx_allocate(Shared_DMA *ctx);void dma_tx_deallocate(Shared_DMA *ctx);void update_rts_line(void);void check_dma_tx_completion(void);void write_pending_bytes_DMA(uint32_t n);void write_pending_bytes_NODMA(uint32_t n);void write_pending_bytes(void);void receive_timestamp_update(void);void thread_init();static void uart_thread(void *);
};

QA1.

  1. 首先,HAL_ChibiOS 是 AP_HAL::HAL这个抽象类的 以ChibiOS为具体操作系统的派生类,所以按照C++惯例,子类构造函数中显式调用基类构造函数即AP_HAL::HAL();
  2. HAL_ChibiOS 相当于已经落实到了具象的操作系统软件硬件平台,比如uartA,他提供具体的:

static HAL_UARTA_DRIVER;

而宏在具体的硬件定义比如fmuv2/ArduPilot_743头文件hwdef.h中:

#define HAL_UARTA_DRIVER ChibiOS::UARTDriver uartADriver(0)

替换完成就是:

ChibiOS::UARTDriver uartADriver(0)

也就是使用ChibiOS领域(namespace)内的UARTDriver 实例化一个对象 uartADriver 并将其地址传入到AP_HAL::HAL基类构造函数中,利用多态特性完成抽象到具体的特化,因为具体的业务逻辑比如ArduCopter或APMrover等凡是在涉及具体软硬件平台方面的操作都是面向接口编程的

故而可以总结业务逻辑层:               ArduCopter ... APMrover\       |         /	-----AP_HAL 层---||----------------------------------/                |                 \软硬件平台层:ChibiOS+fmuv2 ...ChibiOS+fmuv5... linux+树莓派等

这篇关于AP_HAL 分析, 以pixhawk-fmuv2为硬件平台,ChibiOS为底层操作系统:的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1054453

相关文章

Apache 高级配置实战之从连接保持到日志分析的完整指南

《Apache高级配置实战之从连接保持到日志分析的完整指南》本文带你从连接保持优化开始,一路走到访问控制和日志管理,最后用AWStats来分析网站数据,对Apache配置日志分析相关知识感兴趣的朋友... 目录Apache 高级配置实战:从连接保持到日志分析的完整指南前言 一、Apache 连接保持 - 性

Linux中的more 和 less区别对比分析

《Linux中的more和less区别对比分析》在Linux/Unix系统中,more和less都是用于分页查看文本文件的命令,但less是more的增强版,功能更强大,:本文主要介绍Linu... 目录1. 基础功能对比2. 常用操作对比less 的操作3. 实际使用示例4. 为什么推荐 less?5.

spring-gateway filters添加自定义过滤器实现流程分析(可插拔)

《spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔)》:本文主要介绍spring-gatewayfilters添加自定义过滤器实现流程分析(可插拔),本文通过实例图... 目录需求背景需求拆解设计流程及作用域逻辑处理代码逻辑需求背景公司要求,通过公司网络代理访问的请求需要做请

Java集成Onlyoffice的示例代码及场景分析

《Java集成Onlyoffice的示例代码及场景分析》:本文主要介绍Java集成Onlyoffice的示例代码及场景分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 需求场景:实现文档的在线编辑,团队协作总结:两个接口 + 前端页面 + 配置项接口1:一个接口,将o

IDEA下"File is read-only"可能原因分析及"找不到或无法加载主类"的问题

《IDEA下Fileisread-only可能原因分析及找不到或无法加载主类的问题》:本文主要介绍IDEA下Fileisread-only可能原因分析及找不到或无法加载主类的问题,具有很好的参... 目录1.File is read-only”可能原因2.“找不到或无法加载主类”问题的解决总结1.File

Dubbo之SPI机制的实现原理和优势分析

《Dubbo之SPI机制的实现原理和优势分析》:本文主要介绍Dubbo之SPI机制的实现原理和优势,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Dubbo中SPI机制的实现原理和优势JDK 中的 SPI 机制解析Dubbo 中的 SPI 机制解析总结Dubbo中

C#继承之里氏替换原则分析

《C#继承之里氏替换原则分析》:本文主要介绍C#继承之里氏替换原则,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#里氏替换原则一.概念二.语法表现三.类型检查与转换总结C#里氏替换原则一.概念里氏替换原则是面向对象设计的基本原则之一:核心思想:所有引py

基于Go语言实现Base62编码的三种方式以及对比分析

《基于Go语言实现Base62编码的三种方式以及对比分析》Base62编码是一种在字符编码中使用62个字符的编码方式,在计算机科学中,,Go语言是一种静态类型、编译型语言,它由Google开发并开源,... 目录一、标准库现状与解决方案1. 标准库对比表2. 解决方案完整实现代码(含边界处理)二、关键实现细

PostgreSQL 序列(Sequence) 与 Oracle 序列对比差异分析

《PostgreSQL序列(Sequence)与Oracle序列对比差异分析》PostgreSQL和Oracle都提供了序列(Sequence)功能,但在实现细节和使用方式上存在一些重要差异,... 目录PostgreSQL 序列(Sequence) 与 oracle 序列对比一 基本语法对比1.1 创建序

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配