程序的组成、存储与运行

一般 MCU 包含的存储空间有:片内 Flash 与片内 RAM, RAM 相当于内存, Flash 相当于硬盘。编译器会将一个程序分类为好几个部分,分别存储在 MCU 不同的存储区。

一、编译过程

之前分享过C程序的编译过程的笔记:C程序的编译过程是怎样的?

这里先简单看一下MDK的编译过程(它与其它编译器的工作过程是类似的 ):

(1) 编译, MDK 软件使用的编译器是 armccarmasm,它们根据每个 c/c++和汇编源文件编译成对应的以“.o”为后缀名的对象文件(Object Code,也称目标文件),其内容主要是从源文件编译得到的机器码,包含了代码、数据以及调试使用的信息;
(2) 链接,链接器 armlink 把各个.o 文件及库文件链接成一个映像文件.axf.elf

(3) 格式转换,一般来说 Windows 或 Linux 系统使用链接器直接生成可执行映像文件 elf后,内核根据该文件的信息加载后,就可以运行程序了,但在单片机平台上,需要把该文件的内容加载到芯片上,所以还需要对链接器生成的 elf 映像文件利用格式转换器fromelf 转换成.bin.hex文件,交给下载器下载到芯片的 FLASH 或 ROM 中。

这些编译工具都存在于我们MDK的安装目录下,如:

二、程序的组成、存储及运行

程序在我们的MDK编译后,Build Output 窗口显示信息如下:

Program Size 包含以下几个部分:

1) Code:代码段,存放程序的代码部分;
2) RO-data:只读数据段,存放程序中定义的常量;
3) RW-data:读写数据段,存放初始化为非 0 值的全局变量;
4) ZI-data: 0 数据段,存放未初始化的全局变量及初始化为 0 的变量;

编译完工程会生成一个. map 的文件,该文件说明了各个函数占用的尺寸和地址,在文件的最后几行也说明了上面几个字段的关系,如:

1) RO Size 包含了 Code 及 RO-data,表示程序占用 Flash 空间的大小;
2) RW Size 包含了 RW-data 及 ZI-data,表示运行时占用的 RAM 的大小;
3) ROM Size 包含了 Code、 RO Data 以及 RW Data,表示烧写程序所占用的 Flash 空间的大小;

程序运行之前,需要有文件实体被烧录到 STM32 的 Flash 中,一般是 bin 或者 hex 文件,该被烧录文件称为可执行映像文件。STM32程序内存分布如:

左图是可执行映像文件烧录到 STM32 后的内存分布,它包含 RO 段和 RW 段两个部分:其中 RO 段中保存了Code、 RO-data 的数据, RW 段保存了 RW-data 的数据,由于 ZI-data 都是 0,所以未包含在映像文件中。

STM32 在上电启动之后默认从 Flash 启动,启动之后会将 RW 段中的 RW-data(初始化的全局变量)搬运到 RAM 中,但不会搬运 RO 段,即 CPU 的执行代码从 Flash 中读取,另外根据编译器给出的 ZI 地址和大小分配出 ZI 段,并将这块 RAM 区域清零。

其中动态内存堆为未使用的 RAM 空间,应用程序申请和释放的内存块都来自该空间。如下面的例子:

代码中的 msg_ptr 指针指向的 128 字节内存空间位于动态内存堆空间中。

而一些全局变量则是存放于 RW 段和 ZI 段中, RW 段存放的是具有初始值的全局变量(而常量形式的全局变量则放置在 RO 段中,是只读属性的), ZI 段存放的系统未初始化的全局变量,如下面的例子:

sensor_value 存放在 ZI 段中,系统启动后会自动初始化成零(由用户程序或编译器提供的一些库函数初始化成零)。 sensor_inited 变量则存放在 RW 段中,而 sensor_enable 存放在 RO 段中。

三、MDK 工程的文件类型

摘抄整理自:

1、RT-Thread编程手册《um4003-rtthread-programming-manual》
2、野火《零死角玩转STM32—F429挑战者V2》

我的个人博客:https://zhengnianli.github.io/

我的微信公众号:嵌入式大杂烩


 上一篇
C语言代码优化的一些经验及小技巧(二) C语言代码优化的一些经验及小技巧(二)
函数相关1、参数的书写要完整参数的书写要完整,不要贪图省事只写参数的类型而省略参数名字。如果函数没有参数,则用void填充。例如: voidSetValue(intwidth,intheight); // 良好的风格 voidSetValu
2019-08-28
下一篇 
C语言代码优化的一些经验及小技巧(一) C语言代码优化的一些经验及小技巧(一)
一、变量与值得比较1、布尔变量与零值的比较不可将布尔变量直接与 TRUE、 FALSE或者 1、 0进行比较 。据布尔类型的语义,零值为“ 假”(记为 FALSE),任何非零值都是“ 真”(记为TRUE)。 TRUE的值究竟是什么并没有统一
2019-08-27
  目录