MDK编译过程及文件类型全解

1,976 阅读6分钟

C语言编译步骤

1.预处理    gcc -E
2.编译      gcc -S
3.汇编      gcc -C
4.连接      gcc -l
  • 预处理
    • 一般就是处理宏以及头文件
  • 编译
    • 在这个阶段将C语言转化为汇编代码。
    • 一般会进行程序的优化
  • 汇编
    • 将汇编代码转化为机器码
  • 连接
    • 将所有目标文件按照连接脚本的要求进行链接
    • 在这个时候,什么代码段,数据段之类的就可以进行位置的指定了。
      • 在这个阶段就出现了位置无关码之类的名词以及动态链接和静态链接
    • 最终在链接后生成了可执行文件
程序组件 所属类别
机器代码指令 Code
常量 RO-data
初值非0的全局变量 RW-data
初值为0的全局变量 ZI-data
局部变量 ZI-data栈空间
使用malloc动态分配的空间 ZI-data堆空间

ROM可以理解为硬盘,SRAM理解为内存。前者掉电不丢失,但是读写慢,后者掉电丢失,读写快。 ROM中储存了只读(RO-SECTION)段,以及读写段(RW-section)。 显然,RO段是用作bootloader的。而RW段用来存储文件系统的。

程序状态与区域 组成
程序执行时的只读区域(RO) Code + RO data
程序执行时的可读写区域(RW) RW data + ZI data
程序存储时占用的ROM区 Code + RO data + RW data

*.dep,*.d依赖文件

  • Dependency file
    • 记录的是工程或其它文件的依赖,主要记录了引用的头文件路径,其中*.dep是整个工程的依赖,它以工程名命名,而*.d是单个源文件的依赖,它们以对应的源文件名命名。

*.crf交叉引用文件

  • Cross-Reference file
    • 它主要包含了浏览信息(browse information),即源代码中的宏定义、变量及函数的定义和声明的位置。

o、axf及elf文件

  • *.o、*.elf、*.axf以及前面提到的lib文件都是属于目标文件,它们都是使用ELF格式来存储的。
    • Executable and Linking Format
  • 目标文件主要有如下三种类型
    • 可重定位的文件(Relocatable File),包含基础代码和数据,但它的代码及数据都没有指定绝对地址,因此它适合于与其他目标文件链接来创建可执行文件或者共享目标文件。 这种文件一般由编译器根据源代码生成。
    • 可执行文件(Executable File) ,它包含适合于执行的程序,它内部组织的代码数据都有固定的地址(或相对于基地址的偏移),系统可根据这些地址信息把程序加载到内存执行。这种文件一般由链接器根据可重定位文件链接而成,它主要是组织各个可重定位文件,给它们的代码及数据一一打上地址标号,固定其在程序内部的位置,链接后,程序内部各种代码及数据段不可再重定位(即不能再参与链接器的链接)。
    • 共享目标文件(Shared Object File), 它的定义比较难理解,我们直接举例,MDK生成的*.lib文件就属于共享目标文件,它可以继续参与链接,加入到可执行文件之中。另外,Linux的.so,如/lib/ glibc-2.5.so,Windows的DLL都属于这一类

常见文件类型

sct 分散加载文件的格式与应用

当工程按默认配置构建时, MDK 会根据我们选择的芯片型号,获知芯片的内部 FLASH 及内部 SRAM 存储器概况,生成一个以工程名命名的后缀为*.sct 的分散加载文件 (Linker Control File, scatter loading)。

程序启动后链接地址和启动地址有可能不一样。会有一段程序将所有的程序自举到链接地址指定的地方。

野火rt1052 pro为例子

储存 大小(十进制) 大小(十六进制) 起始地址
片上储存 RAM(ITCM) 512K 0x0008 0000 0x0000 0000
off-chip SDRAM 32M 0x0‭200 0000‬ 0x8000 0000
QSPI nor Flash 32M 0x0200 0000 这个是由自己映射的
NAND Flash 128M 0x8000 0000 同样是自己映射的
片上 DTCM 512k 0x0008 0000 0x2000 0000

假设使用 QSPI nor flash。将其映射到 0x80000000的地址(SEMC external memories 起始地址)。

#define m_data_start                   0x80000000
#define m_data_size                    0x01E00000

#define m_ncache_start                 0x81E00000
#define m_ncache_size                  0x00200000

#define m_data2_start                  0x20000000
#define m_data2_size                   0x00020000

#define m_data3_start                  0x20200000
#define m_data3_size                   0x00040000

如上,分为了四个段。

  • m_data_startm_ncache_start共同占据所有QSPI nor flash的地址。
  • m_data2_startm_data3_start共同占据部分DTCM区域
  • 那么最上面图中IRAM2配置的就是ITCM的区域了。只不过ITCM的大小是可以配置的。猜测是为了兼容以前的芯片。
    • 不过以前只是用过arm9。不清楚ITCM的操作,等以后补上。
程序状态与区域 组成
程序执行时的只读区域(RO) Code + RO Data
程序执行时的读写区域(RW) RW Data+ ZI Data
程序储存时的占用区域(ROM) Code + RO Data +RW Data
节区属性描述符 说明
RO code & Code 只读代码段
RO Data & Const 只读数据段
RO & TEXT 包括RO code 和 RO Data
RW Data 读写数据段
RW CODE 读写代码段
RW & Data 包括 RW Data 和 RW Code
ZI & BSS 初始为0的段
XO 只可执行的段
ENTRY 节区的入口

上面m_data_start表示的是片上chip的可读写区域开始地址。

  • m_flash_config_start就是片上flash的起始地址以及大小。
  • m_data2_start就是片外的sdram的起始地址以及大小。

更正

*.sct 文件 改成 *.scf文件。在工程文件中没找到*.sct。兴许是改名字了。但是没找到关于官方文件的解释。暂且先这样。

参考资料

MDK的编译过程及文件类型全解     https://flash-rtd.readthedocs.io/zh_CN/latest/
MDK的帮助手册   《ARM Development Tools》
Keil sct分散加载文件    https://blog.csdn.net/kobesdu/article/details/38258449
KEIL下分散加载文件  *.sct文件 http://www.cnblogs.com/darren-715/p/3457214.html
MDK的编译过程及文件类型全解 https://www.cnblogs.com/yangguang-it/p/7697967.html
配置DTCM,ITCM和OCRAM       http://forum.armfly.com/forum.php?mod=viewthread&tid=86733
如何让RT1050的代码运行速度飞起来  http://www.eeworld.com.cn/mp/ZLG/a57247.jspx