上期讲到此处:(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 的详细及汇总信息。它的内容中主要包含了“节区的跨文件引用”、“删除无用节区”、“符号映像表”、“存储器映像索引”以及“映像组件大小”。
- 节区的跨文件引用:详细列出了各个 *.o 文件之间的符号引用。由于 *.o 文件是由 asm 或 c/c 源文件编译后生成的,各个文件及文件内的节区间互相独立,链接器根据它们之间的互相引用链接起来。
- 删除无用节区:部分列出了在链接过程它发现工程中未被引用的节区,这些未被引用的节区将会被删除 (指不加入到 *.axf 文件,不是指在 *.o 文件删除),这样可以防止这些无用数据占用程序空间。
- 符号映像表:列出了被引用的各个符号在存储器中的具体地址、占据的空间大小等信息。
- 存储器映像索引:相对于符号映像表,这个索引表描述的单位是节区,而且它描述的主要信息中包含了节区的类型及属性,由此可以区分 Code、RO-data、RW-data 及 ZI-data。
- 映像组件大小:这部分包含了各个使用到的 *.o 文件的空间汇总信息、整个工程的空间汇总信息以及占用不同类型存储器的空间汇总信息,它们分类描述了具体占据的 Code、RO-data、RW-data 及 ZI-data 的大小,并根据这些大小统计出占据ROM的总空间。
当工程按默认配置构建时,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段放在起始位置。
文章讲解部分 完结
欢迎关注逗比小憨憨后面将是视频教程,视频教程讲解的内容要比文章部分讲的多
,