PX4IO的编译过程、代码构架以及与PX4FMU的通讯分析

2023-05-16

看到很多教程中讲到PX4飞控的协处理器的作用,包括各类遥控器信号的输入、PWM信号输出、以及与FMU的通讯。但是究竟如何实现的,最近几天自己看代码总算搞懂了,在这里分享一下。

一,代码的组成和编译过程。

    原始代码的主要代码位于 Firmware/src/modules/px4iofirmware文件夹中。打开CMakeList.txt文件,可以看到包含的文件还有位于其他文件夹中的部分源文件,以及apps、nuttx、nosys等等库文件。其实在编译的过程中,针对具体对象的make指令会新建一个build_XXX文件夹,然后将需要编译的源代码和产生的中间过程都放进去,而一些独立的模块会编译成库文件,比如libnuttx.a 就是针对nuttx系统生成的库文件,在CMakeList中在使用add_link_libraries实现功能块的链接。


以上截图来自Firmware/src/modules/px4iofirmwareCMakeList.txt文件

    指定编译目标的指令是add_executable,最后再使用自定义的px4_nuttx_create_bin的CMake自定义function来生成px4io-v2.bin文件。整个编译过程结束之后果然可以在Firmware/build_px4fmu-v2_default/src/modules/px4iofirmware 文件夹中找到这两个文件。

  

以上截图来自Firmware/src/modules/px4iofirmware/CMakeList.txt文件


二、源码分析。

    要分析源码首先需要知道各函数的执行顺序,打开链接文件ld.script,可以看到整个代码使用的flash空间是从0x08001000开始的60K空间,之前的空间被bootloader占据。代码的入口函数是__start,与PX4FMU相同;熟悉PX4FMU启动过程的朋友都知道,接下来会进行一系列OS的启动过程,最后到os_bringup建立第一个用户任务。这也就是nuttx模块可以作为链接库来复用的原因,因为具有相同的执行过程。利用CONFIG_USER_ENTRYPOINT宏进入用户定义的函数中,对PX4FMU来说这个入口是nsh_main()函数;对PX4IO来说,这个入口是usr_start()函数,位于Firmware/src/modules/px4iofirmware/px4io.c文件中。


以上截图来自ld.script文件


以上截图例子os_bingup()函数

    usr_start()函数首先进行了相关的初始化过程,然后进入了一个for( ; ; )循环。也就是说,PX4IO除了系统自带的idle任务之外,只会运行这一个任务,非常类似于简单的裸机嵌入式程序。这也是由IO芯片相对简单的功能属性决定的。

    IO芯片的功能,最关键的就是遥控输入采集和PWM输出,但这都与FMU的通讯关系密切。usr_main()的初始化中调用interface_init()函数初始化了与FMU通讯的串口,设置了串口的波特率,串口的发送和接收都设置为DMA方式;循环部分的controls_tick()函数则用来进行通讯,在这里面实现遥控输入采集和PWM输出的调用。

    controls_tick()函数依次检查DSM、SBUS、PPM三种接收机的数据更新情况,将遥控器数据保存到r_page_raw_rc_input[]数组中,这个数组的结构挺复杂,同时保存了各种遥控输入的状态和原始遥控输入数据,一言半语讲不清楚,有兴趣的朋友可以自己去看代码;然后进行了死区检测、归一化(其实是归10000化,看代码)、重定向、失控保护检测等,将计算结果转存到对应的数组中。


死区检测+归一化,截图来自Firmware/src/modules/px4iofirmware/controls.c文件


失控保护检测,截图来自Firmware/src/modules/px4iofirmware/controls.c文件

    与FMU通讯中的数据接收,采用了中断方式。在interface_init()中定义了串口的中断服务函数为serial_interrupt(),并开启中断。serial_interrupt()接收数据、清楚中断后,再调用rx_dma_callback()进行DMA数据的处理。从这里可以分成了接收和发送两部分,接收部分调用了rx_handle_packet()函数处理对应包的内容,并准备好发送的内容;发送部分则直接使能DMA发送功能完成数据发送。截图中rx_代表数据接收,tx_代表数据发送,tx_dma是串口发送数据的句柄,首先计算CRC写入dma_packet里,然后设置DMA的地址和包大小,然后stm32_dmastart()使能DMA完成数据发送。


PX4IO在中断中进行数据接收和发送处理的过程,截图来自Firmware/src/modules/px4iofirmware/serial.c文件

    从以上处理过程可以看出,PX4IO不会主动向PX4FMU发送任何数据,所有的发送都出于接收到数据之后的回复。protocol.h文件中定义了串口通讯的帧结构,是按照page来分别发送不同的数据的。

参考文章:https://blog.csdn.net/czyv587/article/details/51445308 

这篇后面有一张每个page的列表。

    除此之外,usr_start()的大循环中还会执行check_reboot(),这与PX4IO的固件升级有关。因为固件升级必须重新进入bootloader,因此必须重新芯片。

三、PX4FMU中与PX4IO通讯的代码。

    这部分代码位于Firmware/src/drivers/px4io文件夹中,也有一个名为px4io的文件,但是后缀是.cpp不是.c。与FMU中所有任务的入口函数类似都是XXX_main()的形式,在px4io.cpp文件中的函数名是px4io_main,从这里可以带参数调用各种与IO芯片相关的操作。下面介绍从rcS文件中使用到的参数出发,来看其中几个。

    rcS文件,从上往下,第一次调用px4io 是这里。px4io checkcrc ,在往前一点可以看到,这是对之前编译生成的px4io-v2.bin文件进行CRC检测,目的是在进行固件烧写的串口通讯中,可以让PX4IO芯片的bootloader确认完整无误的收到了整个用于升级固件的文件。


截图来自rcS文件

    第二次使用是 px4io forceupdate 14662 ${IO_FILE},这是将固件烧写进PX4IO芯片。具体实现过程中,与PX4IO中check_reboot()函数关系密切。

    然后就是 px4io start,作用是创建一个新的任务,实现与PX4IO的通讯。落实到代码中就是调用start()函数,在start()函数中,get_interface()获取与IO芯片通讯的串口的设备指针,new一个PX4IO类,在构造函数中将this指针赋值给当前namespace中的g_dev指针变量,以后就可以用这个指针来直接调用新建PX4IO类实例中的所有成员。

    接下来使用g_dev指针调用g_dev->init()来完成所需的初始化工作,在init()函数的最后,创建一个task,入口函数是PX4IO::task_main_trampoline,更进一步,转入实际的入口PX4IO::task_main()。


PX4IO::init()函数中建立的任务

    在task_mian()的主循环中,主要的工作有:根据msg的内容设置控制组,按照IO_POLL_INTERVAL的时长从IO芯片获取状态、遥控输入、PWM输出。同时发布对应的orb消息,以供飞控其他功能模块使用。


PX4IO::task_main()循环中实现的一些功能

写在最后:最近有开发需求,所有想看看遥控指令究竟如何获得,结果顺带分析了一遍PX4IO芯片的程序实现过程。其中有很多猜想的内容,原因是对 Linux下ARM开发 和 C++语言 的知识有限,难免有些错误。只希望可以给像我一下的菜鸟一些参考。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PX4IO的编译过程、代码构架以及与PX4FMU的通讯分析 的相关文章

  • 《即兴演讲》读书笔记

    这是一本我一直在寻找的书 xff1b 因为我从事技术工作 xff0c 十多年来每天都和计算机打交道 xff0c 很少有机会站在台上讲话 xff1b 我对演讲是敬畏的 xff0c 想上台表现自己但心里又充满了恐惧 xff1b 偶尔的上台机会只
  • 读“赵4老师”言论

    在查看CSDN论坛时 xff0c 发现 赵4老师 无处不在 xff0c 赵4老师 通常不会直接给出答案 xff0c 而是直接复制言论 赵4老师的语言虽然很 犀利 xff0c 但仔细想想 xff0c 有些还是有道理的 xff0c 至少帮助我从
  • *.map文件

    关于linux程序的map文件 xff0c 网络上资料很少 xff0c 大概看了下map文件 xff0c 虽然理解的不是很透彻 xff0c 但是还是对程序的编译 运行 内存分配有了一点新的认识 1 map文件是程序的全局符号 源文件和代码行
  • “异常处理”学习小结

    在我经历过的项目中 xff0c 很少使用异常处理 xff1b 对于问题的调试与追踪 xff0c 基本上都是基于错误码和日志信息 这里的学习总结来自于 lt lt C 43 43 编程思想 第2卷 gt gt 和网络 xff0c 有很多问题的
  • 重载new和delete检测内存泄漏

    内存泄漏就是new出来的内存没有通过delete合理的释放 重载new和delete检测内存泄漏原理是 xff1a 在重载的new中记录内存分配情况 xff0c 在重载的delete中删除内存分配记录 xff0c 从而跟踪所有内存分配信息
  • 《Effective C++》读后感

    几天前 xff0c 我曾在微信朋友圈中发了一条消息 xff1a 和大牛之间的差距就是这一个书架 图片来自于微信公众号 二爷鉴书 的分享 我时常纠结于自己的技术为什么进步的这么慢 xff0c 大概就是书读的太少 思考的太少 Effective
  • 《模仿游戏》观后感

    xfeff xfeff 几天前 xff0c 一个朋友让我给他推荐一部电影 xff0c 我思来想去 xff0c 推荐了 模仿游戏 这部电影讲述的是 计算机科学之父 艾伦 图灵在二战期间与其团队一起发明机器 英格玛 破译德国密码系统的故事 关于
  • 对项目的理解

    xfeff xfeff 又有好久没有更新博客了 xff0c 虽然我一直告诫自己 xff0c 不管有多忙都要找点时间来写博客 最近主要的精力都投入到项目中 xff0c 我就说说自己的一些想法吧 1 项目的前期是最忙的 xff0c 投入最大 当
  • 对项目的理解(2)

    xfeff xfeff 项目是做不完的 xff0c 把近期的一些想法写出来 xff1a 1 项目初期做好每一个功能的方案 项目初期 xff0c 有一个辅助功能被我忽略了 xff0c 以为 很容易实现 xff0c 就没有花时间去研究 xff0
  • 5 AI道德风险之偏见风险测试

    AI系统的偏见也包含不公平的一些倾向性反馈 主要是指AI系统提供了一些不准确的反馈 这些反馈有明显的偏见和不公平的特征 这种偏见大部分是因为训练用的数据集存在偏见性而导致的 那么除此之外还有可能受测试和评估因素 人类因素等多种原因影响 因此
  • 解决新版vscode在git merge代码的时候,解决代码冲突的选项按钮不见的问题

    由于vscode新版本中 xff0c 在git merge代码的时候 xff0c 解决代码冲突的选项按钮不见了 xff0c 目前了解1 70 0 1 80 0版本都有这个问题 xff0c 如图 xff1a 解决方法 点击设置搜索 merge
  • 人工智能的过去

    人工智能的起源 xff1a 人工智能在五六十年代时正式提出 xff0c 1950年 xff0c 一位名叫马文 明斯基 后被人称为 人工智能之父 的大四学生与他的同学邓恩 埃德蒙一起 xff0c 建造了世界上第一台神经网络计算机 这也被看做是
  • NVIDIA Jetson Xavier NX入门(1)——烧写系统镜像

    1 Jetson Xavier NX简介 Jetson Xavier NX是一款形状 外接口类似于树莓派的嵌入式主板 xff0c 搭载了6核NVIDIA CarmelARM v8 264位CPU xff0c GPU则是有384g个NVIDI
  • NVIDIA Jetson Xavier NX入门(2)——开机设置和远程登录

    1 开机设置 如果系统镜像烧录成功的话 xff0c 插入SD卡后 xff0c NVIDIA Jetson Xavier NX就可以直接运行了 系统是定制的Ubuntu18 04 xff0c 开机后同意协议 xff0c 一直点击continu
  • 我是如何记笔记的--谈谈自己的学习方法

    本文由 庆哥小白 授权投稿 作者公众号 xff1a 一个自学的程序员 关于记笔记的重要性 xff0c 暂且不谈 xff0c 这次主要说说我在学习的过程中是如何记笔记的 xff01 本文共有 2908 字 如果觉得页面很长 那是因为我很用心
  • docker中apt-get失败

    docker中无法联网导致apt get失败 ERROR1解决方法 ERROR2解决方法 ERROR3解决方法 ERROR1 使用apt get update更新失败 报错 xff1a Err 19 http archive ubuntu
  • pycharm 报错 ModuleNotFoundError: No module named '_cffi_backend'

    Here 39 s the output of pip freeze for reference root 64 machine pip freeze argparse 61 61 1 2 1 autobahn 61 61 0 8 10 c
  • 虚拟Ubuntu 18.04中创建virtualbox 报错:this kernel requires an x86-64 CPU, but only detects an i686 CPU, un

    In addition for running 64 bit guests it is recommended to enable the Input Output APIC in the System gt Motherboard set
  • ubuntu--20.04 安装中文输入法(google拼音)

    安装指令 xff1a sudo apt get install language pack zh hans sudo apt get install fcitx googlepinyin 配置 xff1a 1 搜索框输入 xff1a Lan
  • 装完Ubuntu20.04 之后发现没有声音输出,解决方法

    装完Ubuntu之后发现没有声音输出 xff0c 解决方法 在设置里面的sound选项里面没有多余的声音输出选项 xff0c 多次重启也无法解决 方法 xff1a 1 安装pavucontrol sudo apt install pavuc

随机推荐