嵌入式交叉编译与烧录-基于STM32实战
嵌入式交叉编译与烧录-基于STM32实战
1.CMake和Makefile以及CMakeLists.txt相关知识
1.1关于三个名词的理解。
CMakeLists.txt——唯一与开发者交互
- 它是一个文本文件,里面写的是CMake语法的高级代码。
- 它的核心作用是:用更人性化的语句(比如add_executable),声明项目叫什么名字、包含哪些.c源文件、要链接哪些库、头文件在哪里。
- 开发者通常只需要会修改文件即可,不需要从零手写。
CMake——一个连接CMakeLists.txt和Makefile的软件
- 它不是脚本,而是一个软件程序(在终端里敲的
cmake命令)。 - 它的主要作用是:读取 CMakeLists.txt,并根据当前系统环境(Linux/Mac/Windows)和指定的工具链,自动生成底层的 Makefile。
- 它不是脚本,而是一个软件程序(在终端里敲的
Makefile——面向编译管理工具的文件
- 它是由 CMake 自动生成的、面向编译管理工具的文件。
- 它里面极其繁琐地记录了哪一个.c文件依赖哪一个.h文件,以及编译它需要执行哪一条具体的 arm-none-eabi-gcc 编译命令。
- 因为它太难手写,所以现代开发都交由CMake自动生成。
1.2三者之间的关系。
总的来说,这三者是层层递进的关系,流程是开发者编写CMakeLists.txt——>CMake读取后生成Makefile——>编译器根据Makefile进行编译——>生成.elf文件(最终编译的结果)。但是这三者的目的仅仅是在为编译器做准备工作,相当于在写最终的执行方案Makefile,只是Makefile太过于复杂,所以用了中间工具CMake读取MakeLists.txt生成Makefile.
2.核心开发流程(四个阶段)
- 配置阶段(找到那个.cmake文件)
- 目的:生成Makefile。
- 命令:cmake -DCMAKE_TOOLCHAIN_FILE=…/cmake/gcc-arm-none-eabi.cmake …
- 关键:指定了“交叉编译器工具链”,告诉 CMake 我们是为 ARM Cortex-M 芯片编译,而非PC。
cmake-DCMAKE_TOOLCHAIN_FILE=../cmake/gcc-arm-none-eabi.cmake..- 编译阶段
- 目的:将 C 语言源码翻译成芯片能懂的机器码。
- 命令:cmake --build .
- 关键:属于“增量编译”。如果只修改了 main.c,只会重新编译改变的文件,节省时间。如果清空了build文件夹,则需要重新运行“配置阶段”命令。
cmake--build.//注意目录转换到build文件夹下(这里统一存放编译生成的.elf/.map文件等等)产物分析
- .elf 文件:包含完整的机器码和调试信息,用于烧录和 GDB 调试。
- .map 文件:内存映射文件,记录了每个函数和变量在 Flash/RAM 中的具体绝对地址与大小(例如:main 函数成功定位在 Flash 的 0x080004b0 地址)。
烧录运行
- 目的:将固件写入芯片并让它跑起来。
- 命令:openocd -f interface/stlink.cfg -f target/stm32f1x.cfg -c “program CM_LED.elf reset exit”
- 关键:使用 OpenOCD 工具。program 负责写入,必须加上 reset 芯片才会重新启动并执行新程序。
openocd-finterface/stlink.cfg-ftarget/stm32f1x.cfg-c"program CM_LED.elf resetexit3.注意
3.1注意编译环境
上述编译过程均是基于linux环境下进行,因此在STM32CubeMX中选择CMake或者Makefile。在windows环境下交叉编译可以借助现成的编译器,比如CLion和STM32CubeMX结合使用,本例中是将STM32CubeMX生成的模板代码进行添加相应功能后在CMakeLists.txt文件中添加相应逻辑。
3.2注意工具链的位置和文件管理
在工程目录下创建一个build文件夹,每次重新编译前将该文件夹清空,然后编译的产物全部放在一个文件夹中,方便调试,把工具和结果分开防止分不清。
