李成笔记网

专注域名、站长SEO知识分享与实战技巧

《STM32入门学习第三阶段》Keil MDK的编译过程及文件类型分析讲解

上期讲到此处:(doubixiaohanhan.sct中的内容后面会解释)

doubixiaohanhan.sct中的内容:

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0x08000000 0x00010000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00010000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x20000000 0x00005000  {  ; RW data
   .ANY (+RW +ZI)
  }
}

扩展知识点:在链接的过程中,会用到一个描述文件,用来指定链接时的行为。这个描述文件叫做链接文件,如linux下的.ld文件,keil中的分散加载文件(.sct文件)


armar.exe、fromelf.exe 及用户指令

armar 工具用于把工程打包成库文件(扩展知识点:在Linux下使用ar命令生成静态库文件

ar    rc    libxxx.a xxx.o

),fromelf.exe 可根据 axf 文件生成 hex、bin 文件,hex(51单片机常用的下载文件格式) 和 bin(arm常用下载格式) 文件是大多数下载器支持的下载文件格式。在 keil MDK 中,针对 armar 和 fromelf 工具的选项几乎没有,仅集成了生成hex或 Lib 的选项如下图所示:控制 fromelf 生成 hex 及控制 armar 生成 lib 的配置 。

使用fromelf生成bin文件,可以在keil MDK 的“Option for Target->User”页中添加调用 fromelf 的指令,如下图所示,在 keil MDK 中添加指令 (默认是没有指令的)。

解释:

Before Compile C/C++ File:表示在编译C/C++文件之前生成

Before Build/Rebuild:表示在构建/重新构建工程前生成

After Build/Rebuild:表示在构建/重新构建工程后生成(使用最多的)

比如:我们在构建工程后,利用fromelf将.axf文件转为bin文件

上述语法格式:fromelf --bin --output 想要输出的.bin 具体的.axf文件

例子:fromelf --bin --output C:\Users\PC\Desktop\STM32F103C8T6\program\STM32F103C8T6升级版\USER\obj\doubixiaohanhan.bin C:\Users\PC\Desktop\STM32F103C8T6\program\STM32F103C8T6升级版\USER\obj\doubixiaohanhan.axf

扩展知识点:keil MDK工程中各种类型的文件解释:

以上三张图片摘自网上(本人难得建立表格重新输入,直接用网上的图片,侵权联系必删)

备注:

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

*.crf 是交叉引用文件 (Cross-Reference fifile),它主要包含了浏览信息 (browse information),即源代码中的宏定义、变量及函数的定义和声明的位置。我们在代码编辑器中点击“Go To Defifinition Of ‘xxxx’”可实现浏览跳转,见图浏览信息 ,跳转的时候,keil MDK 就是通过 *.crf 文件查找出跳转位置的。

.axf 文件是由多个.o 文件链接而成的,而 *.o 文件由相应的源文件编译而成,一个源文件对应一个 *.o 文件。

  • ELF 文件头:用来描述整个文件的组织,例如数据的大小端格式,程序头、节区头在文件中
  • 的位置等。
  • 程序头:告诉系统如何加载程序,例如程序主体存储在本文件的哪个位置,程序的大小,程
  • 序要加载到内存什么地址等等。
  • 节区:是 *.o 文件的独立数据区域,它包含提供给链接视图使用的大量信息,如指令 (Code)、数据 (RO、RW、ZI-data)、符号表 (函数、变量名等)、重定位信息等。
  • 节区头:存储在最后的节区头则包含了本文件节区的信息,如节区名称、大小等等。

使用 fromelf 文件可以查看 *.o、.axf 及.lib 文件的 ELF 信息

步骤:

1,在工程模板中的obj目录下打开命令行: shift + 鼠标右键

2,点击 "在此处打开Powershell窗口(S)"

3,使用fromelf命令:比如:fromelf --text -v doubixiaohanhan.axf > doubixiaohahan.txt

doubixiaohahan.txt中内容:


========================================================================

** ELF Header Information

    File Name: .\doubixiaohanhan.axf

    Machine class: ELFCLASS32 (32-bit)            ;注释:32位机,我们使用的是STM32
    Data encoding: ELFDATA2LSB (Little endian)  ;小端格式
    Header version: EV_CURRENT (Current version)
    Operating System ABI: none
    ABI Version: 0
    File Type: ET_EXEC (Executable) (2)   ;可执行文件
    Machine: EM_ARM (ARM)               ;机器版本:arm芯片

    Image Entry point: 0x080000ed    ;映像image入口地址
    Flags: EF_ARM_HASENTRY + EF_ARM_ABI_FLOAT_SOFT (0x05000202)

    ARM ELF revision: 5 (ABI version 2)

    Conforms to Soft float procedure-call standard

    Built with
    Component: ARM Compiler 5.06 update 3 (build 300) Tool: armasm [4d35c6]
    Component: ARM Compiler 5.06 update 3 (build 300) Tool: armlink [4d35c9]

    Header size: 52 bytes (0x34)
    Program header entry size: 32 bytes (0x20)   ;程序头
    Section header entry size: 40 bytes (0x28)    ;段头

    Program header entries: 1    ;程序头入口1个
    Section header entries: 16    ;段头入口16个

    Program header offset: 308688 (0x0004b5d0);程序头在文件中的位置
    Section header offset: 308720 (0x0004b5f0);节区头在文件中的位置

    Section header string table index: 15

========================================================================

** Program header #0

    Type          : PT_LOAD (1)          ;表示这是可加载的内容
    File Offset   : 52 (0x34)            ;在文件中的偏移
    Virtual Addr  : 0x08000000    ;虚拟地址
    Physical Addr : 0x08000000      ;物理地址
    Size in file  : 4220 bytes (0x107c)       ;程序在文件中占据的大小
    Size in memory: 4932 bytes (0x1344);若程序加载到内存,占据的内存空间
    Flags         : PF_X + PF_W + PF_R + PF_ARM_ENTRY (0x80000007)
    Alignment     : 8;地址对齐


========================================================================

** Section #1

    Name        : ER_IROM1
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : SHF_ALLOC + SHF_EXECINSTR (0x00000006)
    Addr        : 0x08000000
    File Offset : 52 (0x34)
    Size        : 4156 bytes (0x103c)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 4
    Entry Size  : 0


====================================

** Section #2

    Name        : RW_IRAM1  ;节区(段)名
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : SHF_ALLOC + SHF_WRITE (0x00000003)
此节区在进程执行过程中占用内存。 节区包含可执行的机器指令。
    Addr        : 0x20000000
    File Offset : 4208 (0x1070)
    Size        : 64 bytes (0x40)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 4
    Entry Size  : 0


====================================

** Section #3

    Name        : RW_IRAM1
    Type        : SHT_NOBITS (0x00000008)
    Flags       : SHF_ALLOC + SHF_WRITE (0x00000003)
    Addr        : 0x20000040
    File Offset : 4272 (0x10b0)
    Size        : 712 bytes (0x2c8)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 8
    Entry Size  : 0


====================================

** Section #4

    Name        : .debug_abbrev
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 4272 (0x10b0)
    Size        : 1476 bytes (0x5c4)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0


====================================

** Section #5

    Name        : .debug_frame
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 5748 (0x1674)
    Size        : 2012 bytes (0x7dc)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0


====================================

** Section #6

    Name        : .debug_info
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 7760 (0x1e50)
    Size        : 26784 bytes (0x68a0)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0


====================================

** Section #7

    Name        : .debug_line
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 34544 (0x86f0)
    Size        : 6972 bytes (0x1b3c)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0


====================================

** Section #8

    Name        : .debug_loc
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 41516 (0xa22c)
    Size        : 2480 bytes (0x9b0)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0


====================================

** Section #9

    Name        : .debug_macinfo
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 43996 (0xabdc)
    Size        : 221552 bytes (0x36170)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0


====================================

** Section #10

    Name        : .debug_pubnames
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 265548 (0x40d4c)
    Size        : 1306 bytes (0x51a)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0


====================================

** Section #11

    Name        : .symtab
    Type        : SHT_SYMTAB (0x00000002)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 266856 (0x41268)
    Size        : 7328 bytes (0x1ca0)
    Link        : Section 12 (.strtab)
    Info        : Last local symbol no = 293
    Alignment   : 4
    Entry Size  : 16


====================================

** Section #12

    Name        : .strtab
    Type        : SHT_STRTAB (0x00000003)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 274184 (0x42f08)
    Size        : 7340 bytes (0x1cac)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0


====================================

** Section #13

    Name        : .note
    Type        : SHT_NOTE (0x00000007)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 281524 (0x44bb4)
    Size        : 28 bytes (0x1c)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 4
    Entry Size  : 0

        Section     Segment
    ====================================

              1           0
              2           0
              3           0

====================================

** Section #14

    Name        : .comment
    Type        : SHT_PROGBITS (0x00000001)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 281552 (0x44bd0)
    Size        : 26980 bytes (0x6964)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0

    Component: ARM Compiler 5.06 update 3 (build 300) Tool: armlink [4d35c9]
    ArmLink --strict --callgraph --map --symbols --xref --diag_suppress=9931 --cpu=Cortex-M3 --list=.\obj\doubixiaohanhan.map --output=.\obj\doubixiaohanhan.axf --scatter=.\obj\doubixiaohanhan.sct --info=summarysizes,sizes,totals,unused,veneers

    E:\keilmdk5Setup\ARM\ARMCC\Bin\..\lib\armlib\c_w.l
    E:\keilmdk5Setup\ARM\ARMCC\Bin\..\lib\armlib\fz_ws.l
    E:\keilmdk5Setup\ARM\ARMCC\Bin\..\lib\armlib\h_w.l
    E:\keilmdk5Setup\ARM\ARMCC\Bin\..\lib\armlib\m_ws.l
    E:\keilmdk5Setup\ARM\ARMCC\Bin\..\lib\armlib\vfpsupport.l
    Input Comments:
 篇幅太长,部分删除
    
    Component: ARM Compiler 5.06 update 3 (build 300) Tool: ArmCC [4d35f0]
    ArmCC --c99 --split_sections --debug -c -o.\obj\usart.o --depend=.\obj\usart.d --cpu=Cortex-M3 --apcs=interwork -O0 --diag_suppress=9931 -I..\CORE -I..\STM32F10x_StdPeriph_Driver\inc -I..\APP\led -I..\APP\button -I..\BIT_Operation -I..\CORE -I..\delay -I..\APP\timer -I..\USART -I..\APP\pwm -I..\APP\capture -I..\APP\ADC -I..\APP\I_temperature -I..\APP\LCD1602 -I..\APP\iwdg -I..\APP\AT24C0X -I..\APP\MPU60X0 -I..\APP\DHT11 -I..\APP\DHT11_2 -I..\APP\myiic -IC:\Users\PC\Desktop\STM32F103C8T6\program\STM32F103C8T6升级版\USER\RTE -IE:\keilmdk5Setup\Keil\STM32F1xx_DFP\2.3.0\Device\Include -IE:\keilmdk5Setup\ARM\CMSIS\Include -D__UVISION_VERSION=521 -DSTM32F10X_MD -DSTM32F10X_MD -DUSE_STDPERIPH_DRIVER --omf_browse=.\obj\usart.crf ..\USART\usart.c
    
    

====================================

** Section #15

    Name        : .shstrtab
    Type        : SHT_STRTAB (0x00000003)
    Flags       : None (0x00000000)
    Addr        : 0x00000000
    File Offset : 308532 (0x4b534)
    Size        : 156 bytes (0x9c)
    Link        : SHN_UNDEF
    Info        : 0
    Alignment   : 1
    Entry Size  : 0


====================================


.map(结合上篇文章中doubixiaohanhan.map进行学习) 文件是由链接器生成的,它主要包含交叉链接信息,查看该文件可以了解工程中各种符号之间的引用以及整个工程的 Code、RO-data、RW-data 以及 ZI-data 的详细及汇总信息。它的内容中主要包含了“节区的跨文件引用”、“删除无用节区”、“符号映像表”、“存储器映像索引”以及“映像组件大小”。

  1. 节区的跨文件引用:详细列出了各个 *.o 文件之间的符号引用。由于 *.o 文件是由 asm 或 c/c++ 源文件编译后生成的,各个文件及文件内的节区间互相独立,链接器根据它们之间的互相引用链接起来。
  2. 删除无用节区:部分列出了在链接过程它发现工程中未被引用的节区,这些未被引用的节区将会被删除 (指不加入到 *.axf 文件,不是指在 *.o 文件删除),这样可以防止这些无用数据占用程序空间。
  3. 符号映像表:列出了被引用的各个符号在存储器中的具体地址、占据的空间大小等信息。
  4. 存储器映像索引:相对于符号映像表,这个索引表描述的单位是节区,而且它描述的主要信息中包含了节区的类型及属性,由此可以区分 Code、RO-data、RW-data 及 ZI-data。
  5. 映像组件大小:这部分包含了各个使用到的 *.o 文件的空间汇总信息、整个工程的空间汇总信息以及占用不同类型存储器的空间汇总信息,它们分类描述了具体占据的 Code、RO-data、RW-data 及 ZI-data 的大小,并根据这些大小统计出占据ROM的总空间。


分散加载文件(链接文件).sct语法

当工程按默认配置构建时,keil MDK 会根据我们选择的芯片型号,获知芯片内部的FLASH 及内部SRAM 存储器概况,生成一个以工程名命名的后缀为 *.sct 的分散加载文件 (Linker Control File,scatter loading),链接器根据该文件的配置分配各个节区地址,生成分散加载代码,因此我们通过修改该文件可以定制具体节区的存储位置。一个分散加载文件由一个或者多个加载域(load regions)组成。每个加载域由一个或者多个执行域(execution regions)组成。执行域中又包含很多个输入段描述(Input section description)。

格式:

加载域名 (基地址 | ("+" 地址偏移)) [属性列表] [最大容量]

{

执行区域

}

加载域名:名称,在 map 文件中的描述会使用该名称来标识空间。用户自定义。

基地址(或称为起始地址): 本加载域的起始地址。分为两种方式:

  • 1),base_address:直接指明本加载域的起始地址。
  • 2),base_address+offset:表示此加载域的起始地址为前一个加载域的结束地址+offset字节。offset必须对齐。

属性列表:属性列表说明了加载域的是否为绝对地址、N 字节对齐等属性,该配置是可选

的。具体取值如下:

  • ABSOLUTE: 绝对地址。默认属性。
  • PI: 与位置无关。
  • RELOC: 可重定位。
  • OVERLAY: 覆盖。
  • NOCOMPRESS: 不能进行压缩。

最大容量(或称为加载域大小(max_size))(可选):指定加载域的最大范围。默认取值0xFFFFFFFF.

执行区域:可以有一个或者多个执行域.

格式:

执行域名 (基地址 | "+" 地址偏移) [属性列表] [最大容量 ]

{

输入节区描述

}

执行域名:名称

基地址(或称为起始地址): 本加载域的起始地址。分为两种方式:

  • 1),base_address:直接指明本加载域的起始地址。
  • 2),base_address+offset:表示此加载域的起始地址为前一个加载域的结束地址+offset字节。offset必须对齐。

属性列表:属性列表说明了加载域的是否为绝对地址、N 字节对齐等属性,该配置是可选

的。具体取值如下:

  • ABSOLUTE: 绝对地址。默认属性。
  • PI: 与位置无关。
  • RELOC: 可重定位。
  • OVERLAY: 覆盖。
  • NOCOMPRESS: 不能进行压缩。

最大容量(或称为加载域大小(max_size))(可选):指定加载域的最大范围。默认取值0xFFFFFFFF.

输入节区:可以有一个或者多个输入段描述.

配合加载域及执行域的配置,在相应的域配置“输入节区描述”即可控制该节区存储到域中,其语法格式如下:通用格式:目标文件过滤器 [+属性]

模块选择样式"(" 输入节区样式",""+" 输入节区属性")"
模块选择样式"(" 输入节区样式",""+" 节区特性")"
模块选择样式"(" 输入符号样式",""+" 节区特性")"
模块选择样式"(" 输入符号样式",""+" 输入节区属性")"

输入节区属性:通过在模块选择样式后面加入输入节区属性,可以选择样式中不同的内容,
每个节区属性描述符前要写一个“+”号,使用空格或“,”号分隔开

目标文件过滤器(模块选择样式)。支持通配符*?。不区分大小写。如main.o,user*.o等。可匹配的文件可以为目标文件名、库名(不带前导路径名)、库完整路径名。可以使用*.o匹配所有的目标文件。用*匹配所有文件,包括目标文件和库。可以使用.ANY进行任意的匹配。它的优先级低于*

属性,不区分大小写:

  • RO-CODE:(或TEXT)只读代码段
  • RO-DATA:(或CONST)只读数据段
  • RO :(或TEXT)即RO-CODE + RO-DATA
  • RW-DATA:可读写数据段
  • RW-CODE:可读写代码段
  • RW:(或DATA) 即RW-DATA + RW-CODE
  • ZI:(或BSS)初始化为0的可读写数据段
  • XO:可执行的区域
  • ENTRY 即包含ENTRY的段,节区入口点
  • FIRST存储到区域的头部,LAST 存储到尾部。通常重要的节区会放在头部,而 CheckSum(校验和)之类的数据会放在尾部。

举例:*.o (RESET, +First) 表示任何目标文件中的RESET段放在起始位置。

文章讲解部分 完结

欢迎关注逗比小憨憨

后面将是视频教程,视频教程讲解的内容要比文章部分讲的多

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言