type
status
date
slug
summary
tags
category
icon
password
week02
流程及目标
总体流程如下:
- 移植综设代码
- 下载综设代码
- 编写Makefile
- 综设项目的修改与调试
- 调试PX4固件
- 编译PX4固件
- 安装相关应用
- 调试PX4固件
目标:能够使用上周搭建的环境来进行综设代码的调试以及PX固件的调试
移植综设代码
下载综设代码
因为我们综设的代码放在了git仓库中,所以可以直接使用git clone指令在网页上下载,而不需要是用FTP等协议将代码从主机传到虚拟机上。因为总体流程很简单,所以就不再赘述了
编写Makefile
首先需要了解Makefile如何编写比较规范,这里就参考STM32CubeMX生成的Makefile进行编写,所以首先需要先看懂STM32CubeMX生成的Makefile
STM32CubeMX的Makefile详解
首先需要知道STM32CubeMX自动生成的Makefile是使用arm-none-eabi-gcc编译链的。下面逐段对自动生成的Makefile进行解释
- 目标文件段
在这里定义了一个变量TARGET来表示目标文件的名称。由于我在STM32CubeMX中设置的项目名称为temp,所以自动生成的Makefile中就认为目标文件的名称应该是temp。当然自己编写Makefile的时候是可以修改目标文件的名称的。
- 构建变量段
- DEBUG变量:表示是否需要产生调试信息,当这个变量为1是,就会在目标代码中带上调试信息
- OPT变量:表示的是gcc指令中的优化等级参数。按照网上的说法:
- 该标识会精心挑选部分与-g选项不冲突的优化选项,当然就能提供合理的优化水平,同时产生较好的可调试信息和对语言标准的遵循程度。
可以看出,当将DEBUG参数设置为1时(也就是使用了-g选项时),最好将gcc的优化等级设置为-Og
至于其他的优化等级以及优化等级的详解,详见:gcc优化参数
- 路径段
- BUILD_DIR:用于指定编译过程中产生的文件存放的位置。上面将该变量的值设置为build就表明将编译生成的文件放在当前工作目录下的build文件夹内。
- 源文件段
- C_SOURCES:该变量用于表示项目中所有的C源文件。所以移植综设代码的时候就需要修改这个变量,以使这个变量表示我们综设项目下的所有的C源文件。
- 注意:Makefile中的\表示的是换行,也就是一行写成多行
- ASM_SOURCES:该变量用于表示项目中所有的.s(注意是小写的s)文件。所以移植综设代码的时候同样需要修改这个变量。
- ASMM_SOURCES:该变量用于表示项目中所有的.S(注意是大写的S)文件。所以移植综设代码的时候同样需要修改这个变量。
- 大小写后缀的区别:
- .s:是一个汇编语言源程序,还需要对其执行的操作有:汇编。也就是说.s文件中并不包含#define等预处理指令,它已经可以直接进行汇编了
- .S:也是一个汇编语言源程序,还需要对其执行的操作有:预处理、汇编。说明.S文件中还能包含#define等预处理指令,所以它还需要经过预处理阶段才能进行汇编
- 关于两种文件的区别,见:关于.s与.S
- 二进制文件段
- PREFIX:表示的是交叉编译链的前缀。由于我们使用的编译链是arm-none-eabi-gcc,所以编译链的前缀就应该是arm-none-eabi-。
- 宏定义GCCPATH:表示的是GCC编译器的路径。根据自动生成的Makefile中给出的注释,可以在终端中设置GCCPATH的值,如:make GCCPATH=xxx。当然也可以不定义GCCPATH,而是选择将gcc编译器的路径配置到环境变量中。我选择的是配置到环境变量中(实际上直接在终端安装的gcc就会放在环境变量中已有的路径下)。
- CC变量:表示gcc指令。当设置GCCPATH时,其表示:GCC路径/arm-none-eabi-gcc;当将gcc编译器的路径配置到环境变量中时,直接使用gcc指令即可,也就是表示:arm-none-eabi-gcc。后面就不再赘述GCCPATH设置与否所造成的影响了
- AS变量:表示汇编处理的gcc指令,用于在gcc指令中增加-x assembler-with-cpp参数
- x: 这个选项后面通常跟随一个语言名称,它告诉编译器接下来的输入文件应该用指定的语言来编译。如果没有指定输入文件,-x 选项会影响随后所有的输入文件,直到遇到另一个 -x 选项。
- assembler-with-cpp: 通常,汇编器预处理的文件具有 .S(大写 S)扩展名,而未经预处理的汇编文件具有 .s(小写 s)扩展名。通过指定 assembler-with-cpp,你可以强制 gcc 使用 C 预处理器(cpp)来处理 .s 文件,就像它处理 .S 文件一样
- 详见:x assembler-with-cpp
- CP变量:表示arm-none-eabi-objcopy。这个指令用于将.elf文件转换为.bin文件(二进制文件)以及.hex文件(十六进制文件)。在下面的HEX以及BIN变量的定义中使用
- 参考:arm-none-eabi把 elf 文件转换成 bin hex文件
- SZ变量:表示arm-none-eabi-size指令。这个指令用于显示程序的文本(代码)、数据和 bss 段的大小。在终端中使用make指令的时候,可以找到如下的输出:
- HEX变量:表示arm-none-eabi-objcopy -O ihex。也就是arm-none-eabi把 elf 文件转换成 bin hex文件中提到的将.elf文件转换为.hex文件的指令。
- BIN变量:表示arm-none-eabi-objcopy -O binary -S。也就是arm-none-eabi把 elf 文件转换成 bin hex文件中提到的将.elf文件转换为.bin文件的指令。但是注意到这里多出来了一个-S选项。
- 根据arm-none-eabi-objcopy使用说明:
所以当在gcc指令中使用了-x assembler-with-cpp这个选项时,我们在.s文件中也能像在.S文件中一样写预处理指令了
这就是执行arm-none-eabi-size指令的输出。
When generating an S-record or a raw binary file, it may be helpful to use -S to remove sections containing debugging information.
也就是说,当需要删除带有调试信息的二进制文件的时候,-S参数就比较有用。因为上面的DEBUG参数设置为1,也就使得我们生成的目标文件(其中就有二进制文件),所以进行删除的时候,最好采用-S参数。这里说的删除应该是重新make的时候生成二进制文件时需要先将原有的二进制文件删除。并且使用说明中也指明了二进制文件所以在将.elf文件转换为.hex文件的时候就没有这个选项了。
- c标识段
- CPU变量:用于表示CPU的型号,也就是处理器的类型,这里由于使用的是综设的板子,所以型号是-mcpu=cortex-m4。
- FPU变量:用于表示浮点运算单元的型号,综设的板子里面自带浮点运算单元,型号为-mfpu=fpv4-sp-d16
- FLOAT-ABI变量:表示的是浮点应用二进制接口。在这里设置为-mfloat-abi=hard,表示的是要使用FPU来进行浮点运算,函数的参数直接传递到FPU的寄存器(s0、d0)中。除了取值为hard以外,-mfloat-abi还可以设置为soft、softfp,详见:mfloat-abi
- MCU变量:表示的是微控制单元(Microcontroller Unit;MCU),也就是单片机。从上面的指令中可以发现,一个单片机应该是由一个CPU、FPU以及指令集(也就是上面的thumb)组成的
- AS_DEFS变量:表示的是gcc汇编宏定义。也就是放与驱动相关的、gcc编译需要的汇编宏定义,而不是放源文件里面的汇编文件
- C_DEFS变量:表示的是gcc中的C宏定义。同样的,这个也是放与驱动相关的、gcc编译需要的C宏定义,而不是放源文件里面C文件
- AS_INCLUDES变量:用于指定汇编头文件的路径。
- C_INCLUDES变量:用于指定C头文件的路径。实际上就是项目中的头文件路径。每一个路径的前面都加上了一个-I选项,表示正在制定头文件的路径。参考:gcc -I -i -L -l 参数区别 / -l(静态库/动态库)
- ASFLAGS变量:用于将上面所有的变量组合起来生成一个交叉编译(所以需要目标单片机的一些信息,也就是MCU信息以及驱动文件,并且要做相应的优化)汇编文件的指令部分。注意到后面多了-Wall -fdata-sections -ffunction-sections。这里实际上是三个选项:-Wall、-fdata-section、 -ffunction-sections
- Wall:当使用这个选项的时候表示将在编译后显示所有警告。关于警告显示的选项,实际上还有-w和-W,这几个警告显示选项的区别详见:gcc中的-w -W和-Wall选项
- fdata-sections:在解释这两个参数之前需要先知道什么是section。GCC链接操作是以section作为最小的处理单元,只要一个section中的某个符号被引用,该section就会被加入到可执行程序中。而-fdata-sections选项会为每一个符号创建一个section,这样就能避免引入不必要的符号,进而减小最终可执行程序的体积
- ffunction-sections:同理,-ffunction-sections选项就是为每一个函数创建一个section,这样就能避免引入不必要的函数,进而减小最终可执行程序的体积。
- 参考:Wall -fdata-sections -ffunction-sections参数
- CFLAGS变量:用于将上面所有的变量组合起来生成生成一个交叉编译C文件的指令部分。后面同样多出了-Wall -fdata-sections -ffunction-sections,含义与ASFLAGS变量中的相同。
- if判断:这里伏笔回收,当指定DEBUG变量为1时就会在gcc指令(也就是上面的CFLAGS变量)中加上-g选项来产生带有调试信息的目标代码,并且通过-gdwarf-2参数来指定生成DWARF2格式的调试信息。关于DWARF2我没有过多了解,之后可以去了解一下。
- 参考:gcc编译选项
- CFLAGS的追加赋值:根据注释,这里的追加赋值是为了生成依赖信息。其中也有三个参数,-MMD、-MP和-MF
- MMD:使用这个选项时,会生成文件关联的信息(也就是文件之间的依赖关系),但是不会包含标准头文件,并且将这些信息写入.d文件中
- MP:生成的依赖文件里面,依赖规则中的所有 .h 依赖项都会在该文件中生成一个伪目标,其不依赖任何其他依赖项。该伪规则将避免删除了对应的头文件而没有更新 “Makefile” 去匹配新的依赖关系而导致 make 出错的情况出现。说白了就是给每一个.h文件都创建一个“替身”,就算原本的.h文件被删除了也能够通过这个“替身”make成功
- MF:用于指定依赖信息需要写入哪个文件。如若有:-MF File,则将依赖关系写入名为 “File” 的文件中
- 参考:Linux Makefile 生成 *.d 依赖文件以及 gcc -M -MF -MP 等相关选项说明
- $(:=) 表示执行 string replacement。如:
- $@表示目标文件,虽然这里的@前面并没有$,但是经过测试表明,这个@还是表示目标文件。如下:
注意到后面还有一个字符串,字符串的内容为:$(@:%.o=%.d)。其中:
则bar变量的值为a.c b.c c.c。也就是进行尾部替换。
这里我设定了一个目标print,然后将变量CFLAGSecho出来时后面跟上的就是我定义的print了
综上,$(@:%.o=%.d)表示为每个 .o 文件生成一个 .d 依赖文件。并且与-MF参数相连,表示依赖信息应该写入这些.d依赖文件中。参考:What does "$(@:%.o=%.d)" mean in a makefile
- 链接标识段
- LDSCRIPT变量:用于表示下载的位置。因为是下载在flash中,所以需要设置为STM32F401RETx_FLASH.ld
- LIBS变量:用于表示使用到的标准库(下载的时候同样需要把库下载到片上很合理吧)。同样有三个选项:
- lc:表示使用c标准库
- lm:表示使用标准数学库
- lnosys:表示使用libnosys库。libnosys库中重新定义了libgloss库(用于提供启动代码和底层I/O支持)中的所有函数,但是所有的函数都是空的,只是为了链接通过而定义的。
- 关于libnosys与libgloss的更多信息,详见:关于newlib中的libgloss和libnosys
- LIBDIR变量:用于指定第三方库的路径。
- LDFLAGS变量:将上述变量整合起来生成一个下载指令的部分,以便将目标文件(.o文件)与库文件一同链接下载到片上。并且生成一个.map文件。看后缀的话也不难猜到.map文件是存储片上映像(映射)信息的。主要的内容有以下几个:
- 节区的跨文件引用(Section Cross References)
- 删除无用节区(Removing Unused input ps from the image)
- 符号映像表(Image Symbol Table (Local Symbols Global Symbols)
- 存储器映像索引(Memory Map of the image)
- 映像组件大小(Image component sizes)
- .map文件应该是在编译过程中产生的,用于为下一步的烧录操作提供指引。关于.map文件详见:STM32 | map文件详解
- all目标:Makefile中的第一个目标就是整个Makefile的目标,所以这个这个Makefile的目标就是生成.elf、.bin、.hex文件。
- 构建段
- 函数addprefix:从字面意思上也能看出来,就是添加前缀的意思。使用方式如下:
- 函数notdir:同样从字面意思上也能看出来,就是去掉字符串中的路径。使用的示例如下:
- 字符串替换:也就是上面提到的$(:=) ,在这里对变量OBJECTS而言就是为CSOURCES中的.c文件在build目录下生成一个.o文件;为ASMSOURCES中的.s文件在build目录下生成一个.o文件;为ASMM_SOURCES中的.S文件在build目录下生成一个.o文件
- vpath关键字:用于指定某一类文件的搜索路径,使用方式如下:
- sort函数:用于去掉重复的文件路径,使用方式如下:
- dir函数:与notdir相反,是去掉文件名,只保留路径
- $@:表示的是目标文件
- |:是管道符号。以这里的使用为例, | $(BUILD_DIR)表示的就是如果要生成目标文件.o文件就要先生成build目录,也就是build目录也是依赖文件;如果生成了build,那么之后就不需要再生成build了。如果去掉管道符号,那么每次make都会重新生成build目录,也就是重新生成所有文件。下面是GNU的原文:
- 创建build目录
- 编译.c文件生成.o文件
- 编译.s文件生成.o文件
- 编译.S文件生成.o文件
- 根据所有的.o文件(也就是OBJECTS变量)生成.elf文件
- 根据.elf文件生成.bin文件以及.hex文件
首先需要了解一些关于Makefile的知识:
经过addprefix函数、notdir函数以及字符串的替换,不难发现OBJECTS就是所有的目标文件(也就是.o文件)
将符合pattern的文件的搜索路径设置为directories
经过处理,vpath就应该通过CSOURCES、ASMSOURCES、ASMM_SOURCES记录了.c、.s、.S文件的搜索路径。
接下来就是根据目标文件以及依赖文件之间的关系,一步步去生成all目标了。从上面的依赖关系,不难发现,编译的过程应该是:
总体逻辑看得出来还是很清晰的。并且通过变量的使用,使得我要写综设的Makefile的时候,只需要修改源文件路径即可,灰常的奈斯。
- 清除段
也就是创建一个伪目标clean用于清除编译生成的所有文件。
- 依赖段
这里实际上是在排除依赖段(也就是排除.d文件),也就是使用了-include指令,表示“减去”一些文件。使用-include的情况如下:
当所包含的文件不存在或者不存在一个规则去创建它,make程序会继续执行,只有真正由于不能正确完成终极目标的重建时(某些必需的目标无法在当前已读取的makefile文件内容中找到正确的重建规则),才会提示致命错误并退出。
但是经过尝试,发现在这里去掉-include并不会报错,可能是为了处于Makefile编写的规范,才将依赖文件进行了-include。关于-include,详见:Makefile中include、-include、sinclude
这里还有一个函数wildcard,表示的是扩展通配符,以在变量的定义或者函数引用时使用通配符(通配符在变量定义以及函数的引用时会失效)。这也可以理解为一个编写Makefile的习惯,就是在使用通配符的时候都加上函数wildcard。关于函数wildcard,详见:Makefile中wildcard的介绍
需要注意的是,“”是通配符,但是“%”不是通配符。也就是说使用“\”时才需要使用函数wildcard,使用“%”的时候不需要使用函数wildcard。参考:关于Makefile中通配符的相关内容,以及‘%’和‘*’的区别
综设项目的Makefile编写
根据上面对自动生成的Makefile的分析,由于使用的开发板是相同的,所以需要修改的地方只有:
- 目标文件段:可以修改一下目标文件的名称
- 路径段:可以修改一下目标文件存放的目录名称
- 源文件段:需要修改为综设项目中的源文件
- c标识段:需要修改头文件的路径
此外还可以添加上一周所写的直接下载(烧录)指令,并将其定义成一条伪命令:
注意:需要修改烧录指令中的烧录文件的路径,所以我选择在Makefile中新建一个变量来表示需要烧录的二进制文件,然后在指令中使用变量,这样就不用一直修改烧录指令中的二进制文件路径了:
其中TARGET_PATH变量定义为:
为了让生成目标文件足够小,我们在c源文件中并不是选择将所有的hal源文件都进行编译,而是选择编译我们所需要的部分。明确了需要修改哪些部分之后,综设项目的Makefile编写就没有什么难度了。
综设项目的修改与调试
- 编写json文件
- 由于之前是使用keil在进行开发,所以没有json文件的存在。现在将项目移植到vscode上,就需要先新建一个json文件,这里就不再追述如何创建一个json文件。由于使用的板子并没有变化,都是STM32F401,所以综设项目的json文件应该与配置环境时的json文件相同,这里直接把配置环境时的json文件复制过来就好了。
- 修改汇编代码
- 之前由于使用的是keil,所以有关汇编文件的编译实际上都是keil帮我们做的,也就不存在什么格式的问题。但是现在是使用gcc进行编译,并且gcc只能识别AT&T格式的汇编文件,所以我们需要将综设项目中的所有的汇编文件都修改为gcc能识别的格式,也就是AT&T格式。庆幸的是,启动文件在配置环境时STM32CubeMX自动生成的就是AT&T格式,所以在这里就能借鉴一下自动生成的启动文件,并且直接用自动生成的启动文件替换原来综设项目的启动文件即可。而不同格式的汇编文件之间,应该有区别的只有机器无关的部分,也就是伪指令部分,具体的机器有关的指令应该都是相同的,都是使用arm汇编指令。所以下面浅浅谈一下修改时发现的一些AT&T与原来我们使用的汇编格式的伪指令区别:
- 注释不再是使用";",而是跟c语言一样使用"//"或者"/**/"进行注释
- EQU微指令需要替换为:
- DCD要替换成.word。
- .word微指令的意思是在当前位置放一个值,所以当需要把DELAY设置为0x00000000时,就需要使用下面的格式:
- AT&T格式中没有proc,也没有end和endp。对于原有的这些伪指令,直接删除就好了。目前来看是没有什么问题的。
- 所有的函数都设置成全局符号:
- .align伪指令
- 使用格式如下:
- .fpu
- 这个指令用于指示目标板的fpu型号。单独把这个拎出来讲是因为在启动文件中,将fpu的型号设置为了软浮点,就会导致我们使用到的一些指令没办法使用,所以在汇编·文件中需要将fpu设置为Makefile里面的fpu型号(这才是我们综设板子上的fpu真正的型号)
- gcc编译环境下ARM汇编语法(伪指令)
- AT&T汇编的伪指令
当一个函数设置为全局符号时,他就是对其他汇编文件可见的,但是在c源文件中如果要使用全局符号还是需要进行extern。所以不难发现,.global实际上就是原来的export伪指令的作用,并且使得汇编文件中不再需要import伪指令。
通常将num设置为2的整数次幂。并且仅在需要指令对齐的地方再使用这条伪命令即可。
参考:
- 添加.ld文件
- 经过对自动生成的Makefile的理解,知道进行程序烧录的时候还需要一个与flash下载有关的.ld文件。同样的,因为板子型号是一样的,所以可以直接把配置环境时的.ld文件复制过来
- 一些小问题
- 除了上面的问题,我还注意到同名的.s文件、.c文件和.S文件不能同时使用。因为如果只有扩展名不一样的话,进行编译的时候,就只会匹配.c文件。因为当想要输出一个.o文件的时候,由于依赖文件为.c文件的规则在最上面,所以会先找.c文件,找到.c文件的时候就不会再去考虑这个.o文件的其他依赖了。也就是说此时汇编文件不会参与编译产生汇编文件自己的.o文件。相关规则如下:
接下来就能正常将综设程序烧录到板子上并进行调试了。
调试PX4固件
编译PX4固件
总体上来说就是安装学长的readme来进行设置即可。
Compile locally
依照readme的提示:
Compile locally
- clone repo.
- run init repo script: ./initallrepo.sh it will take some time to clone all submodules into loccal
- Enter directory NxtPX4-Hardware: cd ./NxtPX4-Hardware you should notice that you are not on main branch, So Checkout to main branch using: git checkout -b main
- cd back to NXTPX4 dir
- Enter directory PX4-Autopilot: cd ./PX4-Autopilot you should notice that you are not on main branch or develop branch. So checkout main branch to local and then checkout to develop branch to compile frameware for NxtPX4. git checkout -b main and then git checkout -b develop origin/develop
- configure done !
所以按照上面的步骤一步一步做就能进行本地编译所需要的设置了
- 首先将学长提供的git仓库克隆到本地,可以发现里面就带了一个repo的shell脚本:
这个时候进到Hardware以及Autopilot目录,里面是没有东西的,需要使用脚本将子模块克隆到本地
- 执行脚本
- 也就是在NxtPX4目录下,在终端中输入:
将子模块全都克隆到本地
- 切换为主分支
- 进入到NxtPX4-Hardware目录之后,根据学长的提示,此时我们并不在主分支上:
- b:表示创建一个新的分支并且切换到该分支
所以此时需要切换到主分支。在终端中输入:
这里使用到一个git指令的选项
由于我们发现此时main分支已经存在,所以这个-b选项不是必须的。
此时再次使用git branch指令,就能发现我们在主分支上了:
- 返回父目录
- 直接在终端中输入:
即可。
- 切换为develop分支
- 进入到PX4-Autopilot目录之后,发现本地是没有main分支的:
根据学长的提示,我们需要先在本地上创建一个main分支。也就需要在终端中输入:
此时我们就在本地创建了一个main分支并且已经切换到main分支上了:
接下来我们需要切换到develop分支,也就是需要在终端中输入:
这样这个本地的develop分支就会跟踪远程仓库中的develop分支。并且指令执行之后我们就已经在本地的develop分支上了:
至此本地编译的设置结束。
Setting up NxtPX4
学长在这里主要指出了一个问题,也就是串口1和串口2出现打印错误的问题。而出现问题的原因是V1.2.3 PCB上的丝印层将串口1和串口2的Tx和Rx标反了。
v1.2.3(错误版本):
v1.2.3.1(正确版本):
Compile PX4Firmware
也就是进行PX4固件的编译了。
学长在readme中提供了两种编译方式:
- 使用make
- 学长在这里指出,如果要使用PX4 1.14.x firmware的话就需要将PX4-Autopilot目录切换到develop_v1.14.x分支。这里我选择使用这个固件(因为看着版本号比较新),所以步骤如下:
- 进入PX4-Autoplilot目录
- 也就是在终端中输入:
- 切换分支为develop_v1.14.x
- 首先先查看当前目录的分支,输入:
- 编译bootloader
- 对于PX4 1.14.x firmware,需要输入:因为我目前还没有修改这个项目中的文件,所以按照终端的提示,应该输入u来解决这个问题,最终编译成功:
- 烧录bootloader
- 首先需要先下载QGC以及PX4模拟器
- 下载QGC
- 学长在这里使用到了QCG进行设置,所以在这里先安装一个QGC。
- 用户设置:
- 依次在终端中输入下面的指令:
- 安装QGC
- 需要在上面提供的页面中下载:QGroundControl.AppImage。
- 下载PX4模拟器
- 可以在PX4的官网上下载一个PX4模拟器:PX4模拟器
- 编译固件
- 对于PX4 1.14.x firmware,需要输入:
显示:
其中的develop_v1.14.x就是我们需要切换的分支。
在终端中输入:
就将分支切换到develop_v1.14.x了。
编译时可能会遇到有一些软件没有安装,只要照着终端的提示全部安装上就能正常编译了。
在编译的过程中,出现下面这个问题:
在编译的过程中一直弹出一个警告: jobserver 不可用: 正使用 -j1。添加 “+” 到父 make 的规则。
关于这个警告产生的原因,详见:警告解决方案
因为在综设项目中暂时还没有涉及到bootloader,所以在这里浅浅介绍一下bootloader。
在嵌入式操作系统中,BootLoader是在操作系统内核运行之前运行。可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。
也就是说BootLoader是嵌入式系统在加电后执行的第一段代码,在它完成CPU和相关硬件的初始化之后,再将操作系统映像或固化的嵌入式应用程序装载到内存中然后跳转到操作系统所在的空间,启动操作系统运行。
参考:BootLoader
官网上有提供ubuntu上QCG的安装教程:安装QGC
接下来就需要注销用户然后重新登录来使能上面的这些用户配置
然后要进入到安装目录(一般都是Download目录),然后输入下面的指令:
然后就能正常使用QGC了:
在官网中提到实际上ubuntu22.04已经安装了Gazebo Simulation,所以只需要进行一些设置即可。在进行PX4固件调试的时候就先不用师兄提供的代码了,而是选择直接调试PX4源码。
下载PX4源码:
剩下的就是重启虚拟机了
当然之后如果需要去调试师兄的代码并且还是没有硬件设备的话,就需要去看看
编译成功:
当然如果出现了上面编译bootloader的情况,就安装终端的提示来走就好了
在编译的过程中可能出现一些指令not found或者一些软件没有安装的情况,这个时候同样根据终端的提示来安装即可。其中有一个软件包需要使用老版本:
终端中的提示为:
但是进行编译时仍然会报错(模块"em"没有属性"RAW_OPT"):
从网上找到一个解决方案,是说empy的版本问题:AttributeError:"模块"对象没有属性"RAW_OPT"
在终端中输入:
安装一个老版本的empy就能正常编译了
- 使用docker
- 当然在使用docker之前需要安装一下docker的,根据终端的提示安装docker:
- 编译bootloader
- 因为使用的是develop_v1.14.x分支,所以需要在终端中输入:
- 编译固件
- 同样的,需要在终端中输入:
但是给出的网址一直报503,所以就只能在终端中或者在官网上安装docker了。
根据终端的提示输入:
为了再尝试一下使用docker,所以需要先将之前生成的目标文件删除:
学长在这里提供的docker的使用方法:
不难发现这个docker实际上也是一个脚本
在运行docker命令的时候出现下面的问题:
说明是权限不够,所以就在终端中切换一下身份,临时切换成root用户,再执行指令即可。当然也可以加上sudo
运行过程中还出现了下面的问题:
说是没有找到镜像,这个时候就会直接去pull下来。pull结束之后就会像make编译一样开始编译了。
编译成功。
其余的步骤跟上面的编译bootloader是一样的,这里就不再赘述了。
编译成功。
在原来的仓库中是没有build脚本的,但是前几天学长刚刚在仓库上更新了这个脚本,并且放在了主目录下(所以这个时候就不能在PX4-Autoplilot目录下打指令了),所以现在就能通过docker进行编译了
PX4的学习就暂时到这里了。。。
其他参考
- 作者:Noah
- 链接:https://imnoah.top/article/PX4/Week02
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。