利用gcc-arm-none-eabi开源工具链开发STM32程序

2023-11-17

一、前言

入门STM32开发时,用的是keil 这个IDE。后面因为要提高开发效率和keil 版权问题,选择开源的arm-none-eabi-gcc ,通过命令行调用make工具进行编译、链接、烧录,打包。

二、要达到的效果

2.1 编译STM32 工程

make all

2.2 烧录单片机

make install

三、几个重要的问题点

3.1 如何高效地编译每一个源文件

3.1.1 源文件编译的原理

我们知道,编译器是对每一个源文件进行编译,生成对象文件,然后再把所有的对象文件链接起来,生成最终的elf文件。一个工程那么多源文件,怎么高效地组织源文件进行编译?

3.1.2 常见的一些组织源文件的方式

我之前在网上看到的做法,都是在makefile 文件中定义一个C_SOURCES 变量 , 作为源文件容器, 将工程中的源文件,都一一写到这个变量中去,然后在后面的处理中,利用这个C_SOURCES 变量 进行处理。

3.1.3 存在的问题

一个工程那么大,每次添加或减少一个源文件,或者代码重构时,移动源文件的路径,都要修改一次makefile ,太麻烦。按照一般的处理,makefile 文件更新时,都会重新编译整个工程,效率太低。

3.1.4 自动生成源文件列表

C_SOURCES =$(shell find . -name "*.c")

这里利用了make的shell 函数,调用外部bash 的find 命令,找到所有的当前目录下的.c 文件,保存到列表中。我们也可以利用这个思路,解决源文件并不完全在当前目录的情况。

3.2 如何找到所有的头文件

与前面描述源文件的情况类似,我们需要自动生成一个所有头文件的路径的列表。
C_INCLUDES=$(addprefix -I, sort $(dir $(shell find . -name "*.h")))

  • 利用make 的shell函数,调用外部bash 的find 命令,找到当前工程的所有.h 文件(包含路径)。
  • 我们需要的其实是路径。所以调用make 的dir 命令,截取路径。
  • 如果同一个路径下,有多个.h 文件,我们上述处理后,会有重复的路径。所以调用make 的sort 命令,主要是为了利用它过滤掉重复字符串的特性。
  • 上述处理,已经得到工程中所有头文件的路径。由于gcc 寻找头文件时,需要在每个路径前面加 ‘-I’ 前缀,所以,调用make的addprefix 函数,给每个路径加上-I 前缀。

3.3 怎么解决头文件依赖关系

每个源文件都可能包含一个或者多个头文件,它包含的头文件还可能包含其他头文件。我们要解决的问题有两个:

3.3.1 怎样高效找到源文件依赖的所有头文件

gcc 的-M 选项自动生成目标文件和源文件和依赖关系。-M 选项会把系统头文件都包含进来,如果不需要输出系统头文件的依赖关系,可以-MM 选项。一般情况下,依赖文件是后缀为.d 的文件。例如main.c 的依赖文件是main.d 。

CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"

$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
    $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
3.3.2 依赖的头文件修改了,怎么自动编译源文件

上面针对所有的.c 文件生成依赖文件(.d)文件存放在BUILD_DIR 目录下。依赖文件,以规则的语法,列出了对象文件的依赖头文件
在这里插入图片描述
在这里插入图片描述

既然依赖文件是一条条规则,我们将所有的规则包含进makefile,make就可以自动推导了
-include $(wildcard $(BUILD_DIR)/*.d)

3.4 编译链接优化问题

3.4.1 设置编译优化等级

$(CC) -O2 main.c -o main.o

3.4.2 没使用的函数不链接
  • 在编译源文件时,在gcc 编译选项中增加 -ffunction-sections、-fdata-sections , 在编译生成的目标文件中,会将每个函数或者数据段,放在单独的section中。
  • 在前面的基础上,链接对象文件时,加上-Wl,--gc-sections 参数,链接器不会链接未使用的函数,从而达到压缩hex文件的目的。

四、 用到的make 相关知识整理

4.1 shell 函数的用法

  • shell 函数的参数是操作系统的shell 命令,shell函数把执行操作系统命令后的输出作为函数返回。
    函数使用格式如下:

  • $(shell <shell cmd> <shell cmd argmuments>)

  • 示例:
    contents := $(shell cat foo)

4.2 排序函数sort

  • $(sort <list>)
  • 函数给列表中的子字符串排序(升序),并且会去掉相同的子串
  • 示例: $(sort foo bar lose) 返回 bar foo lose

4.3 取目录函数dir

  • $(dir <names...> )
  • 从文件名系列中取出目录部分,目录部分是指最后一个反斜杠(/)之前的部分。如果没有反斜杠,那么返回./
  • 示例:$(dir src/foo.c hacks) 返回 src/ ./

4.4 加前缀函数

  • $(addprefix <prefix>, <names...> )
  • 把前缀 加到 中的每个字符串前面。返回加过前缀的字符串系列。
  • 示例:$(addprefix src/, foo bar) 返回 src/foo src/bar

五、makefile 源码

gitee

六、参考链接:

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

利用gcc-arm-none-eabi开源工具链开发STM32程序 的相关文章

随机推荐

  • 前端获取本地ip地址

    在某些场合的情况下 后台可能需要前端电脑的ip 因为每台电脑的ip不一样 所有需要动态获取 翻翻网上写的很多 里面其实是很坑的 因为都是在调用闭包函数 所以执行起来是没有任何问题的 但是 你页面想拿的时候 你是没法拿到的 下面就一vue 为
  • Ubuntu18.04 谷歌浏览器安装教程

    Ubuntu 经验笔记 Ubuntu18 04 谷歌浏览器安装教程 1 测试环境 2 安装步骤 Ubuntu18 04 谷歌浏览器安装教程 1 测试环境 系统版本 Ubuntu 18 04 安装时间 2021年7月4日 2 安装步骤 启动终
  • 区块链学习笔记(八)——应用之有机大米的一生

    区块链学习笔记 八 应用之有机大米的一生 前言 一 张三申请加入村里合作社的有机大米农业区块链项目 二 大米种植全程上链 三 有机大米收获出售过程上链 总结 前言 其实区块链的现实应用很多 我们用有机大米种植销售为例来看看它的应用 麻将四人
  • 设备怎样开启位置服务器,开启设备服务器

    开启设备服务器 内容精选 换一换 使用远程登录方式连接登录Windows云服务器时出现如下错误 此计算机无法连接到远程计算机 服务端安全组3389端口未开启 检查云服务器端口配置 服务端防火墙关闭 检查防火墙配置是否正常远程桌面连接配置不正
  • BMP存储方式

    BMP存储像素值的方式为从下至上 从左至右 紧随着文件头存储的字节为图像最下一行的数值 从左下角开始依次存储 22 22 22 23 为图像左下角像素的数值 依次向右存储 最后一行扫描完后 紧接着存储上一行 最后一个byte存储的是图像右上
  • Java中位数

    中位数 输入数组长度n 和n个数 输出这n个数的中位数 当结果为小数时向下取整 输入用例 1 1 输出用例 1 输入用例 2 3 3 输出用例 3 输入用例 5 5 3 1 2 4 输出用例 3 import java util Scann
  • 【ESP-IDF】2.ESP32C3移植u8g2显示库驱动OLED

    前言 这个系列的文章属于是为了一碟醋包了一顿饺子系列 起因是看到tb上某家店的ESP32C3开发板才9 9包邮 想着研究一下 把手头有个用Arduino UNO实现的项目升级一下 于是就有了这个系列 ESP32C3的简介 2020 年末 乐
  • React Navigation(三)-StackActions(API)

    原文链接 StackActions对象包含了生成特定actions的方法 即基于栈导航器的actions 这些方法扩展了NavigationActions 支持以下actions Reset 用一个新的状态替换当前状态 Replace 用其
  • Python 人脸表情识别

    人脸表情识别 一 图片预处理 二 数据集划分 三 识别笑脸 四 Dlib提取人脸特征识别笑脸和非笑脸 参考 环境搭建可查看Python人脸识别微笑检测 数据集可在https inc ucsd edu mplab wordpress inde
  • 阿里云CDN缓存预热与刷新以及常见的故障汇总

    文章目录 1 为CDN缓存的文件增加过期时间 2 CDN缓存预热配置 3 CDN缓存刷新配置 4 常见故障 CDN缓存预热指的是主动将要缓存的文件推送到全国各地的CDN边缘加速器上 减少回源率 提供命中率 缓存刷新指的是后期上传了同名的文件
  • ubuntu9.10 虚拟机连接windows网络上网,以及NFS挂载网络设置。

    1 虚拟机设置 2 关掉网卡 sudo ifconfig ethxx down 3 打开网卡 sudo ifconfig ethxx up 4 打开浏览器就可以使用网络上网了 NFS 1 vmware软件设置网络连接方式 2 选择桥接方式
  • 写了placement new也要写placement delete——条款52

    placement new和placement delete并非C 兽栏中最常见的动物 如果你不熟悉它们 不要感到挫折或忧虑 回忆条款16和17 当你写一个new表达式像这样 Widget pw new Widget 共有两个函数被调用 一
  • 映射表原理分析与总结

    在使用本地缓存时 经常用到映射表 大家都知道映射表保存数据的原理是将key做hash再取余 余数落在数组的不同索引中 利用数组的索引获取元素 时间复杂度为O 1 这样查询速度很快了 但是也存在一个问题 那就是如果两个key落到同一个索引桶上
  • 使用js获取上传文件的真实路径

    我们在使用html中的
  • 闭关之现代 C++ 笔记汇总(二):特性演化

    目录 前言 C 98 C 98 之前 C 98 的主要语言特性 特性总结 dynamic cast RAII 标准库组件 总结 find if 其他语言对 C 影响 非 C 98 内容 C 对其他语言影响 非 C 98 内容 C 11 C
  • java jre jvm_JVM、JRE和JDK的关系

    JVM Java Virtual Machine是Java虚拟机 Java程序需要运行在虚拟机上 不同的平台有自己的虚拟机 因此Java语言可以实现跨平台 JRE Java Runtime Environment包括Java虚拟机和Java
  • 并发问题(二)什么是并发

    1 什么是并发操作 并发操作是指同一时间可能有多个用户对同一数据进行读写操作 2 并发操作对数据的影响 如果对并发操作不做任何控制的话 会造成数据的不完整性 可能造成读脏数据 不可重复读 丢失修改还有幻读 3 对数据不完整性的举例 1 丢失
  • Java Spring Boot 框架

    Java Spring Boot 框架 Spring Boot是一个用于快速构建独立 生产级别的Java应用程序的开源框架 它是Spring Framework的扩展 旨在简化Spring应用程序的开发和部署 并提供一个约定优于配置的开发模
  • MYSQL5.1 WINDOWS环境下导出查询数据到EXCEL文件

    今天做一个多表的联合查询 用myadmin不支持导出 于是找到下面的方法 不错 查询出来的记录 导出到EXCEL文件 直接做报表输出 测试环境WINDOWS XP OFFICE 2003 MYSQL 5 1 451 创建一个测试表 3个字段
  • 利用gcc-arm-none-eabi开源工具链开发STM32程序

    一 前言 入门STM32开发时 用的是keil 这个IDE 后面因为要提高开发效率和keil 版权问题 选择开源的arm none eabi gcc 通过命令行调用make工具进行编译 链接 烧录 打包 二 要达到的效果 2 1 编译STM