stm32专题三十六:MDK编译过程和文件类型(二)

stm32专栏 专栏收录该内容
83 篇文章 19 订阅

MDK工程的文件类型:

1 下图为 Project 目录下的工程文件

实际上,只需要有 unprojx 文件,就可以恢复整个工程。

具体描述:

2 源文件

3 output 和 list 文件

详细分析:

1 uvprojx 文件

uvprojx 文件就是我们平时双击打开的工程文件,它记录了整个工程的结构,如芯片类型、工程包含了哪些源文件等内容。

可以使用vscode直接打开 uvprojx ,来看一下里面的具体内容:

2 uvoptx 文件

uvoptx 文件记录了工程的配置选项,如下载器的类型、变量跟踪配置、断点位置以及当前已打开的文件等。

我们在程序 main.c 的第81行设置断点,观察uvoptx的输出情况:

结果如下:

包括下载器类型等配置:

3 uvguix 文件

uvguix 文件记录了 MDK 软件的 GUI 布局,如代码编辑区窗口的大小、编译输出提示窗口的位置等。

uvprojx、 uvoptx 及 uvguix 都是使用 XML 格式记录的文件,若使用记事本打开可以看到 XML 代码。而当使用 MDK 软件打开时,它根据这些文件的 XML 记录加载工程的各种参数,使得我们每次重新打开工程时,都能恢复上一次的工作环境。这些工程参数都是当 MDK 正常退出时才会被写入保存,所以若 MDK 错误退出时(如使用 Windows 的任务管理器强制关闭),工程配置参数的最新更改是不会被记录的,重新打开工程时要再次配置。根据这几个文件的记录类型,可以知道 uvprojx 文件是最重要的,
删掉它我们就无法再正常打开工程了,而 uvoptx 及 uvguix 文件并不是必须的,可以删除,重新使用 MDK 打开 uvprojx 工程文件后,会以默认参数重新创建 uvoptx 及 uvguix 文件
。(所以当使用 Git/SVN 等代码管理的时候,往往只保留 uvprojx 文件)。

4 源文件

5 output 目录下生成的文件

在mdk中,可以指定output文件的输出路径:

output生成的文件如下所示:

Ⅰ 静态链接库 .lib文件

得到生成的*.lib 文件后,可把它像 C 文件一样添加到其它工程中,并在该工程调用 lib提供的函数接口,除了不能看到*.lib 文件的源码,在应用方面它跟 C 源文件没有区别。


Ⅱ .dep   .d依赖文件

*.dep 和*.d 文件(Dependency file)记录的是工程或其它文件的依赖, 主要记录了引用的头文件路径, 其中*.dep 是整个工程的依赖, 它以工程名命名, 而*.d 是单个源文件的依赖,它们以对应的源文件名命名。
先看一下.d文件,我们在整个文件夹中选一个.d文件:

直接vscode打开来看一下内容,可以看到,bsp_led.d文件,其实就是记录了bsp_led这个源文件包含的头文件路径。

知道单个文件的依赖以后,那么我们再看下 .dep 文件,记录了整个工程的依赖(记录了所有源文件所包含的头文件路径):

 

Ⅲ .crf 交叉引用文件

打开 .crf 乱码如下:

6 .o .axf .elf文件

ELF 是 Executable and Linking Format 的缩写,译为可执行链接格式,该格式用于记录目标文件的内容。在 Linux 及 Windows 系统下都有使用该格式的文件用于记录应用程序的内容,告诉操作系统如何链接、加载及执行该应用程序。

目标文件主要有 3 种类型:

6 o 文件与 axf 文件的关系

根据上面的分类,我们了解到, *.axf 文件是由多个*.o 文件链接而成的,而*.o 文件由相应的源文件编译而成,一个源文件对应一个*.o 文件。
例如:当我们在main.c中进行修改,如下所示,再点击编译时,由于没有改动其他的源文件,实际上只重新编译了main.c,而原来就生成的其他 .o 文件不需要再参与编译,链接器把新的 .o文件和之前其他 .o文件重新连接成 .elf文件。

然后再进行编译,结果如下:

链接器的作用:

代码如下:

图解过程如下:

7 ELF文件头

接下来我们看看具体文件的内容,使用 fromelf 文件可以查看*.o、 *.axf 及*.lib 文件的ELF 信息。

首先使用windows powershell,查看 fromelf 工具的帮助信息:

根据命令提示,接下来我们使用命令语句来查看bsp_led.o文件的基本信息:

fromelf --text -v .\bsp_led.o   

打印信息如下,可以看到,一下子打印出来了很多信息。

为了方便查看,我们可以使用windows 重定向符号 > 将命令行中输出的内容存储到文件中,具体用法如下:

我们使用如下的命令语句,输出详细信息到txt:

 fromelf --text -v .\bsp_led.o > bsp_led_info.txt

可以看到,在当前目录下新生成了 bsp_led_info.txt 的文件:

同样的,我们也可以生成整个 .axf 文件的详细信息:

 fromelf --text -v .\流水灯.axf > flow_light_info.txt

结果如下:

在之前有分析过 .o 文件的结构如下,包括文件头、程序头(可选)、节区、节区头部表。

现在来看一下 bsp_led.o的文件内容:

接下来是节区信息:

关于节区信息的描述:

接下来看一下 .o文件 和 .elf 文件的对比:

 

再进行一下对比,可以看到,在节区前,elf文件确实存在程序头:

看一下程序头的具体内容:

下面是 MDK 的编译信息:

对照着 MDK 的编译信息,我们来分析一下这个文件:

1 首先是地址,程序头的物理地址和虚拟地址均为0X0800 0000,这是stm32内部flash的起始地址。而由于stm32不带有MMU内存管理单元,因此物理地址就等于虚拟地址;

2 Size in file:1440字节,表示程序在文件中占据的大小。对比上图,我们发现:

Size in file = Code + RO-data + RW-data = 1096 + 336 + 8 = 1440;

3 Size in memory:3976 字节,表示若程序加载到内存,占据的内存空间。 

Size in memory = Code + RO-data + RW-data + ZI-data = 1440 + 2536 = 3976;

4 8字节对齐,这个在freertos中非常常用。

接下来看一下节区信息:

反汇编代码

使用以下语句生成反汇编代码:

fromelf --text -c .\bsp_led.o > bsp_led_o_info.txt   

生成的反汇编代码如下:

经过链接器生成的elf文件,来和.o文件对比看一下:

现在我们可以从汇编代码中清晰的看到,链接后的elf文件,为每个函数都分配了地址,可以调用正确的指令来执行。

分散加载代码

学习至此,还有一个疑问,前面提到程序有存储态及运行态,它们之间应有一个转化过程,把存储在 FLASH 中的 RW-data 数据拷贝至 SRAM。然而我们的工程中并没有编写这样的代码,在汇编文件中也查不到该过程,芯片是如何知道 FLASH 的哪些数据应拷贝到 SRAM 的哪些区域呢?

其实主要是下面这段代码:

 

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值