type
status
date
slug
summary
tags
category
icon
password
2024.1.10~2024.1.17
Steps
使用OpenOCD 下载代码
使用VSCode 对代码打断点调试
移植综合设计开发环境
配置PX4本地编译环境,编译PX4 固件
使用OpenOCD 调试PX4固件 (TODO)
01 · VSCode 开发STM32环境配置(macOS)
“优雅的嵌入式开发。”
一直以来IDE用的太多,代码编译等基本环节知识欠缺了不少,趁此机会仔细琢磨下。对于其他类unix系统,下文步骤中的包管理器和环境变量配置可能有些需要更改的地方。
开发环境
默认已经安装好Homebrew包管理器。使用brew安装的包默认都在/opt/homebrew/文件夹下,并且将自动创建符号链接至路径/opt/homebrew/bin下,不用手动配置环境变量。/opt是“可选项”(optional)的缩写,用于存放可选的、独立于操作系统提供的软件包的文件。
- 研究一下类unix系统的文件构建体系
暂时无法在成电飞书文档外展示此内容
工具链
- 安装交叉编译链 GNU Armmbedded Toolchain
- 打开terminal,输入
- 这一行指令会安装
arm-none-eabi-gcc
、arm-none-eabi-gdb
以及arm-none-eabi-binutils
的完整工具链。 - 安装完毕后,输入
arm-none-eabi-gcc -v
、arm-none-eabi-gdb -v
指令,如果出现版本信息即可
More Versions:developer.arm.com
- 安装openOCD
- 打开terminal,输入
- 看看版本
openocd -v
:
为什么安装openOCD时还显示在安装openCV和PCL之类的?
- 安装STLink
- 打开terminal,输入
- 使用
st-info --probe
查看STlink连接情况
- 终端命令行测试
- 在命令行里使用make与openocd指令对一demo进行测试,解决所有问题后编辑VScode里Workspcae的配置
- 使用Cube32MX快速新建一个点灯的demo;Generate Code时选择“Makefile”选项
- 编译
- 下载
- 两个.cfg文件:stlink.cfg 和 stm32f4x.cfg
- 可以在/OpenOCD/share/openocd/scripts中找到。
- 板载小灯此时亮起,烧录成功。
终端返回(在当前目录新建了build目录)
......
arm-none-eabi-size build/TESTFOROpenOCD.elf
text data bss dec hex filename
4264 20 1572 5856 16e0 build/TESTFOROpenOCD.elf
arm-none-eabi-objcopy -O ihex build/TESTFOROpenOCD.elf build/TESTFOROpenOCD.hex
arm-none-eabi-objcopy -O binary -S build/TESTFOROpenOCD.elf build/TESTFOROpenOCD.bin
终端返回:
VSCode配置
- 编译&下载:配置Task.json
- 配置三个task:编译、烧录以及清除已编译的文件。这样一来,我们仅仅需要通过command+shift+B即可执行上面在命令行中输入的一长串指令。下面以烧录为例,其余两条指令只需要调整command以及args部分。
- 调试:配置Launch.json
- 创建Launch.json,添加如下:
- 需要注意"svdFile"项:svd文件包含了寄存器等信息,是单步调试与查看寄存器信息的关键。该文件可以前往Keil5安装路径的Pack文件夹下查找,也可以前往下面这个网址下载:
https://github.com/modm-io/cmsis-svd-stm32
随即可以开始单点调试
至此,整个开发环境配置完成。
参考
https://lrl52.top/950/linux-build-embedded-env/
https://blog.csdn.net/weixin_54911557/category_12167262.html
https://zhuanlan.zhihu.com/p/145801160
https://zhuanlan.zhihu.com/p/114311741
https://zhuanlan.zhihu.com/p/376450754
https://zhuanlan.zhihu.com/p/468568448
问题
- 遭遇报错:
- 一篇详细的文章讲解高版本gcc对于#include_next的处理
- 临时解决方案:卸载13.2版本的arm-none-eabi-gcc,手动更换为 10.3.1 20210824 (release)版本。
- TODO:macOS与Ubuntu的环境变量管理
- 研究一下/etc/path.d/内的东西
https://www.jianshu.com/p/94faa8d32519
- 什么是SVD文件,作用是什么?
- 描述寄存器映射:SVD文件定义了硬件设备的寄存器映射,包括每个寄存器的地址、大小、访问权限和位域的描述。它提供了一个结构化的方式来描述设备寄存器的布局和功能。
- 自动生成驱动代码:基于SVD文件,可以使用自动化工具生成设备驱动代码。这些代码可以用于访问和配置设备寄存器,简化了驱动程序的编写和维护过程。
- IDE集成和调试支持:一些集成开发环境(IDE)可以使用SVD文件提供硬件的可视化和调试支持。通过加载SVD文件,IDE可以了解设备的寄存器布局和功能,并在调试过程中显示寄存器的状态和值。
- 硬件抽象和代码重用:SVD文件提供了一种硬件抽象的方式,使得应用程序可以与具体的硬件平台解耦。通过使用SVD文件,可以编写可移植的应用程序代码,并在不同的硬件设备上进行重用。
SVD文件是指System View Description文件,它是一种描述硬件设备寄存器映射和外设配置的文件格式。SVD文件通常用于嵌入式系统开发中,特别是在使用CMSIS(Cortex Microcontroller Software Interface Standard)的情况下。
SVD文件的作用如下:
总之,SVD文件是一种用于描述硬件设备寄存器映射和配置的文件格式,它在嵌入式系统开发中扮演着重要的角色,用于生成驱动代码、提供调试支持和实现硬件抽象等功能。
- openOCD如何利用SVD进行调试工作?
- 获取SVD文件:首先,需要获取适用于目标设备的SVD文件。SVD文件通常由芯片厂商提供,可以在芯片或开发板的文档或支持页面上找到。确保选择与目标设备完全匹配的SVD文件。
- 配置OpenOCD:接下来,需要配置OpenOCD以使用SVD文件。打开OpenOCD的配置文件(例如"openocd.cfg"),在配置文件中添加以下内容:
- 启动OpenOCD:通过命令行或集成开发环境(IDE)启动OpenOCD。OpenOCD将根据配置文件加载SVD文件并初始化调试接口。
- 调试和可视化:一旦OpenOCD启动,你可以使用适当的调试工具(例如GDB)连接到OpenOCD,以进行寄存器级别的调试。在调试过程中,OpenOCD将使用SVD文件提供寄存器的名称、位域的描述和当前值,以及其他相关信息。这使得调试过程更加直观和可视化,可以更方便地查看和修改寄存器的状态。
OpenOCD(Open On-Chip Debugger)是一种开源的调试和编程工具,用于与嵌入式系统中的处理器和调试接口进行通信。OpenOCD可以与SVD文件相配合,以提供基于寄存器级别的调试和可视化支持。
以下是OpenOCD与SVD文件相配合的主要步骤:
通过将OpenOCD与SVD文件相配合,可以实现基于寄存器级别的调试和可视化支持,提供更好的开发体验。SVD文件的加载使得调试过程更具可读性和可理解性,帮助开发人员更好地理解和控制目标设备的寄存器状态。
02 · 移植综设开发环境
- 整理一下在ST的标准外设库函数开发环境下的项目架构。移植到Vscode下进行开发后,需要自己理清文件关系与编译命令,才能正确的编写Makefile
暂时无法在成电飞书文档外展示此内容
编译的过程
在编写Makefile前,我们先复习一下编译技术,理清一下使用交叉编译器对ARM-CortexM4架构目标进行编译的过程,以便于我们写好系列Rules。在这里,我们自顶向下的分析一下。理清各种步骤后,可以通过指令
arm-none-eabi-gcc --help
来查看如何调用参数来实现目的需求。最终生成目标——链接系列.o文件
- 在嵌入式开发过程中,最终有三种文件可以烧写到STM32的板子中执行:
.elf
.hex
.bin
- .elf 文件(Executable and Linkable Format):它是一种可执行文件和可链接文件的标准格式。.elf 文件包含了编译器和链接器生成的可执行代码、全局变量、符号表和其他调试信息。它是嵌入式应用程序的最终生成文件,可以用于调试、运行和部署。
- .hex 文件(Intel Hexadecimal Format):它是一种用于存储二进制数据的文本文件格式。.hex 文件通常用于将程序烧录到目标设备的非易失性存储器(如闪存)中。烧录工具可以读取 .hex 文件并将其中的二进制数据按照特定的协议(如 Intel HEX)烧录到目标设备的存储器中。
- .bin 文件(Binary Format):它是一种纯二进制文件,包含了编译器和链接器生成的可执行代码的二进制表示。.bin 文件通常用于将程序直接加载到目标设备的内存中,而不需要使用特定的烧录工具。.bin 文件可以通过串口、JTAG 等方式将程序加载到目标设备中运行。
在开发过程中,我们更多选择烧录
.elf
文件到板子里去。 .hex
.bin
也是用.elf
转换得来的(使用arm-none-eabi-objcopy
)看了看珮泽师兄的Github仓库,是把一个
.px4
文件直接烧录到板子里去。GPT说 “.px4 文件通常是从 .elf 文件生成的,用于无人机飞控系统的固件文件,用于烧录到飞控硬件上实现飞行控制和导航功能。在开发过程中,开发者使用开发工具链(如 PX4 开发工具链)将源代码编译和链接生成 .elf 文件。然后,通过特定的构建和烧录过程,将 .elf 文件转换为 .px4 文件,以便将固件烧录到目标飞控硬件上。”暂时无法在成电飞书文档外展示此内容
所以该如何生成呢?
.hex
O ihex
:这是arm-none-eabi-objcopy
工具的选项之一,用于指定输出文件的格式为 Intel HEX 格式。O
选项表示输出格式,ihex
是指定的输出格式名称。build/HeiGuan.elf
:这是输入文件的路径和名称,表示你要转换格式的 ELF 格式目标文件的路径和名称。build/HeiGuan.hex
:这是输出文件的路径和名称,表示转换后生成的 Intel HEX 格式文件的路径和名称。
.bin
O binary
:同上,指定输出格式为binary
S
:用于剥离(strip)目标文件中的符号信息。在转换过程中,只保留目标文件的原始二进制数据,而不包含符号表等调试信息。build/HeiGuan.elf
:输入文件的路径和名称build/HeiGuan.bin
:输出文件的路径和名称
.elf
xx_1.o
和xx_2.o
:这是输入的目标文件,表示需要编译和链接的对象文件。这些文件可能是通过编译源代码而生成的。mcpu=cortex-m4
:用于指定目标处理器架构为 Cortex-M4。这将确保生成的代码在 Cortex-M4 处理器上正确运行。mthumb
:用于指定使用 Thumb 指令集。Thumb 是一种精简指令集,常用于嵌入式系统开发。mfpu=fpv4-sp-d16
:用于指定浮点运算单元(FPU)的类型。fpv4-sp-d16
表示使用单精度浮点运算(SP)和 16 位数据宽度。mfloat-abi=hard
:用于指定浮点运算的 ABI(Application Binary Interface)。hard
表示使用硬件浮点运算。specs=nano.specs
:用于指定链接时使用的规范文件。nano.specs
是针对资源受限的嵌入式系统的规范文件。TSTM32F401RETx_FLASH.ld
:用于指定链接时使用的链接脚本文件。链接脚本定义了程序加载和内存布局的规则。lc -lm -lnosys
:用于指定链接时需要使用的库文件。lc
表示链接 C 标准库,lm
表示链接数学库,lnosys
表示链接无操作系统库。Wl,-Map=build/HeiGuan.map,--cref
:用于指定链接器的参数。Map=build/HeiGuan.map
表示生成链接地图文件,-cref
表示生成交叉引用信息。Wl,--gc-sections
:这是编译器选项,用于指定链接器对无用代码的剪裁。-gc-sections
表示剪裁无用的代码段,以减小生成的可执行文件的大小。o build/HeiGuan.elf
:这是编译器选项,用于指定输出文件的路径和名称。build/HeiGuan.elf
表示生成的可执行文件的路径和名称。
生成elf文件就需要用到链接器了。在交叉编译环节中,除了指定输入的系列
.o
文件,还需要指定系列目标平台的处理器架构、指令集等细节选项。在这里,需要查阅对应芯片的手册来确定一些关键选项:中间文件.o
的生成——分别编译.c和.s
暂时无法在成电飞书文档外展示此内容
我们需要使用gcc编译器将.s与.c文件编译为.o文件,系列.o文件将被用于生成.elf文件。除了.o文件,还有一些可以选择生成的.d和.lst文件。这两个文件是为了在编译过程中提供附加的信息和辅助功能。
1. 生成
.d
文件(依赖关系文件):
1. .d
文件记录了源代码文件及其依赖项之间的依赖关系。这些依赖关系包括头文件的引用和其他源代码文件的引用。
2. 当一个源文件发生修改时,.d
文件可以被用来确定需要重新编译的文件,以及需要重新链接的目标文件。
3. 这对于大型项目和多文件项目非常有用,因为它可以避免不必要的重新编译,提高编译效率。
2. 生成 .lst
文件(汇编列表文件):
1. .lst
文件提供了对汇编代码的详细分析和解释。它包含了源代码的汇编表示,以及与之对应的机器指令和地址。
2. .lst
文件对于调试和代码优化非常有用。它可以帮助开发人员理解编译器生成的汇编代码,并进行针对性的优化和调试。
3. 通过查看 .lst
文件,可以了解编译器如何处理代码,如何分配寄存器和内存,并对代码执行路径进行分析。- 1.
- 1.
- 2.
- 3.
生成
.d
文件(依赖关系文件):.d
文件记录了源代码文件及其依赖项之间的依赖关系。这些依赖关系包括头文件的引用和其他源代码文件的引用。当一个源文件发生修改时,
.d
文件可以被用来确定需要重新编译的文件,以及需要重新链接的目标文件。这对于大型项目和多文件项目非常有用,因为它可以避免不必要的重新编译,提高编译效率。
.d
文件记录了源代码文件及其依赖项之间的依赖关系。这些依赖关系包括头文件的引用和其他源代码文件的引用。
- 当一个源文件发生修改时,
.d
文件可以被用来确定需要重新编译的文件,以及需要重新链接的目标文件。
- 这对于大型项目和多文件项目非常有用,因为它可以避免不必要的重新编译,提高编译效率。
- 2.
- 1.
- 2.
- 3.
生成
.lst
文件(汇编列表文件):.lst
文件提供了对汇编代码的详细分析和解释。它包含了源代码的汇编表示,以及与之对应的机器指令和地址。.lst
文件对于调试和代码优化非常有用。它可以帮助开发人员理解编译器生成的汇编代码,并进行针对性的优化和调试。通过查看
.lst
文件,可以了解编译器如何处理代码,如何分配寄存器和内存,并对代码执行路径进行分析。.lst
文件提供了对汇编代码的详细分析和解释。它包含了源代码的汇编表示,以及与之对应的机器指令和地址。
.lst
文件对于调试和代码优化非常有用。它可以帮助开发人员理解编译器生成的汇编代码,并进行针对性的优化和调试。
- 通过查看
.lst
文件,可以了解编译器如何处理代码,如何分配寄存器和内存,并对代码执行路径进行分析。
- 从汇编文件生成.o文件
- 这里有一个坑,前些日子一直报错,后来莫名其妙的解决了。昨天子为联系我说不同编译工具链的汇编文件语法不同,才恍然大悟。之前在Keil5中编写的.s都基于MDK工具链,而现在移植的环境是在gcc工具链。
x assembler-with-cpp
:这是编译器选项,用于指定输入文件的类型为带有预处理指令的汇编源代码。这使得编译器能够识别并处理源文件中的预处理指令。c
:用于指定只进行编译操作,而不进行链接操作。这将生成一个目标文件,而不是可执行文件。DUSE_STDPERIPH_DRIVER
和DSTM32F401xx
:定义宏。I./CORE/ -I./Hardware/ -I./Library/ -I./User/
:用于指定头文件的搜索路径。I
选项后面跟着的路径表示头文件的目录路径。Og
:这是编译器选项,用于指定优化级别。Og
表示进行调试级别的优化,以保留调试信息和原始代码的可读性。Wall
:这是编译器选项,用于启用所有警告信息。fdata-sections
和ffunction-sections
:这是编译器选项,用于将数据和函数放置在单独的节(section)中。这有助于在链接时进行无用代码的剪裁。g -gdwarf-2
:这是编译器选项,用于生成调试信息。g
表示生成调试信息,gdwarf-2
表示生成 DWARF 2 格式的调试信息。MMD -MP -MF"build/startup_stm32f401xe.d"
:这是编译器选项,用于生成依赖关系文件。MMD
表示生成依赖关系文件,MP
表示生成包含所有目标文件的规则,MF
指定依赖关系文件的名称和路径。startup_stm32f401xe.s
:这是输入的汇编源代码文件的路径和名称。o build/startup_stm32f401xe.o
:这是编译器选项,用于指定输出文件的路径和名称。build/startup_stm32f401xe.o
表示生成的目标文件的路径和名称。
在这里仍然需要调用
arm-none-eabi-gcc
,并如上文中生成.elf
文件时指定处理器架构、指令集、浮点运算单元类型。除此之外,还需要额外指定:- 从源文件生成.o文件
c
:别忘了加上这个。在这里我们先只进行编译,不进行链接。Wa,-a,-ad,-alms=build/main.lst
:用于生成汇编代码的附加输出。Wa
后面跟着的参数用于指定附加输出的选项,a
表示生成汇编代码,ad
表示在汇编代码中包含所有指令的二进制表示,alms=build/main.lst
表示将汇编代码输出到名为build/main.lst
的文件。
与上文从汇编文件生成并没有太多区别。值得注意的一点不同是:从.c文件生成.o文件时需要顺便生成.d和.lst两种文件 (汇编只用生成.d)。.lst文件是原代码的汇编表示,通过查看.lst文件可以分析编译器如何处理代码,如何分配寄存器等细节问题,便于进行深层次的DEBUG操作。
这样,整个流程就顺下来了:
暂时无法在成电飞书文档外展示此内容
接下来就要考虑怎么写Makefile了。需要思考好Rule之间的关系,再构造足够多的变量用于保存命令中的那一大堆参数。
Makefile编写
https://lrl52.top/305/makefile/
将上述
- ./
Makefile
- 在这里,我参照CubeMX生成的demo中的Makefile,对以下部分进行了修改:
- 由于标准外设库函数的.c实在过多,此时选用了
find
命令来在当前目录和其子目录中递归搜索文件名匹配.c
的所有文件 - 之前的C_DEFS就是我们在Keil5中点小魔术棒中输入的宏定义。注意📢:根据gcc参数的规则,宏定义前需要加上
D
- 这里配置头文件。需要注意的是,只需要将头文件所在目录丢给链接器即可,在书写这里的路径时不能具体到文件名
xxxx.h
- 但是整个编译过程的几条Rules还没有理清楚,稍后下来仔细研究一下
startup_stm32f401xe.s
- 一个普普通通的启动汇编文件,其中包含了系统初始化、中断服务和跳转到main函数的过程。但是直接复制粘贴Keil工程里的该文件会报错说找不到函数SystemInit和main函数的声明,此时我们需要在
.global
一行下添加: STM32F401RETx_FLASH.ld
- 一个链接脚本文件,用于在使用 STM32F401RETx 微控制器进行嵌入式软件开发时,定义了存储器布局和链接器的行为。 链接脚本文件是由链接器使用的配置文件,它指定了可执行程序在内存中的布局,包括代码、数据和其他部分的存放位置和大小。它还定义了链接器如何组织、分配和对齐代码和数据。
./Script
- 其中存储了F401RE的SVD文件
./CORE
- stm32f4xx.h
- core_cm4.h
- RTE_Components.h
- system_stm32f4xx.h
- system_stm32f4xx.c
./Hardware
- 放置自己写的系列硬件模块的驱动
./Library
- 放置标准外设库函数
- 注意📢,此处需要删除fsmc和fms外设的文件
./User
- 放置主函数、中断服务、Delay等函数的文件
03 · 配置PX4固件本地编译环境
克隆代码
开始编译
cd到PX4-Autopilot里去使用make hkust_nxt_bootloader来编译bootloader(make hkust_nxt-v1_bootloader用于编译develop_v1.14.x版本)使用make hkust_nxt来编译飞控固件(make hkust_nxt-v1用于编译develop_v1.14.x版本)
- 一种简单的方法,可以直接配置好所有需要依赖的包
但是由于此前电脑中已经安装了很多很多包,就打算直接硬make一发,按着报错来装pakage。
- 遭遇了几个报错
- CMake Version
- 电脑里安装的是3.28版本的cmake,感到非常奇怪,不知道为什么说cmake版本低于3.5。后来才发现是高于3.5版本的Cmake将不再与低于3.5版本的CmakeList兼容,但是这里的CMakeList兼容低于3.5版本的cmake;cmake在构建工程时就会面临一种版本箭筒问题的不确定性, 于是将CmakeList开篇的
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
中的3.2改为3.5即可解决该问题。 - 提示策略CMP0148已被移除的warning
- 在CMake中,Policy(策略)是用来管理不同cmake版本之间行为和功能的变化的。策略定义了CMake的某个特定方面的行为规则。每个策略都有一个唯一的名称(CMPXXXX),其中XXXX是一个数字。通过设置相应的策略,你可以控制CMake的行为是否遵循新的规则或保持与旧版本的兼容性。
- 这个Warnning主要是对项目开发者看的,如果只是变一下来直接用,那使用
Wno-dev
指令即可让这条warnning不再出现;但为了彻底解决这个警告,我们需要使用cmake_policy指令来设置CMP0148的行为。 - 根据提示安装对应的包
- 需要注意empy的版本。最新的版本已经移除了
.RAW_OPT
属性,需要指定安装版本3.3.4 - 编译完后链接静态库失败:too many open files
- 没想到链接时除了问题,文件数过多,这时候需要修改一下系统的限制了。最后查出来是zsh把打开文件的最大数量限制到了256。遂改为65535,成功编译
参考
找到一个较为全面的PX4新手指南
问题
- NxtPX4上的TF卡是做什么的?如何指定PX4固件下载的地址与Bootloader下载的地址?
PX4-Autopilot文件架构
- 没有在根目录的Makefile里找到hkust_nxt_bootloader的rule?
04 · 本地调试PX4固件
- 焊接上了,但是st-link移植检测不到设备😭
看看STM32H7的手册吧
似乎找到原因了,H7默认使用JTAG,要切换到SWD需要:
- 作者:CrystalPuNK
- 链接:https://crystalpunk.top/article/11c5d734-b731-800f-ab73-c7607f87f337
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。