Keil分散加载文件浅析
1ARM映像文件组成
ARM 映像文件其实就是源文件经编译器生成的目标文件,一般是bin文件或者hex文件,可以直接烧录到ROM中执行(一般是内部FLASH),这个文件称为可执行映像文件(image file)。
映像文件一般由域组成,域最多由三个输出段组成(RO,RW,ZI)组成,输出段又由输入段组成。所谓域,指的就是整个映像文件所处在的区域,它又分为加载域和运行域。我们输入的代码,一般有代码部分和数据部分,这就是所谓的输入段,经过编译后就变成了映像文件中的RO段和RW段,还有所谓的ZI段,这就是输出段。
●加载域:映像文件被静态存放的工作区域。
●运行域:程序运行起来的存储区域。
程序在存储状态时,RO段及RW段都被保存在ROM区。
当程序开始运行时,内核直接从 ROM 中读取代码,并且在执行主体代码前,会先执行一段加载代码,它把 RW 段数据从 ROM 复制到 RAM,并且在 RAM加入 ZI 段,ZI 段的数据都被初始化为 0。加载完后 RAM 区准备完毕,正式开始执行主体程序。
2分散加载机制
分散加载机制允许开发者为代码或数据变量在加载和执行时指定不同的存储空间,通知链接器把程序的某一部分链接在存储器的某个地址空间。
2.1 何时使用分散加载
实现嵌入式系统通常需要分散加载,这些系统使用ROM、RAM和内存映射的外设。通常需要分散加载的情况如下:
1)复杂内存映射:
必须放置在许多不同内存区域的代码和数据需要详细的指令来说明在内存空间中放置这些部分的位置。
2)不同类型的内存:
许多系统包含各种物理存储设备,如FLASH、ROM、SDRAM和快速SRAM。分散加载描述可以将代码和数据与最合适的内存类型相匹配。例如,中断代码可以放在快速的SRAM中以改善中断响应时间,但不常用的配置信息可以放在较慢的闪存中。
3)内存映射的外设:
分散加载描述可以将数据段放置在内存映射中的精确地址上,以便可以访问内存映射的外设。
4)函数在固定位置:
即使周围的应用程序已被修改和重新编译,也可以将函数放置在内存中的相同位置。这对于跳转表的实现很有用。
5)使用符号来标识堆和堆栈:
在链接应用程序时,可以为堆和堆栈位置定义符号。
2.2 怎么使用分散加载
1)对于具有简单内存映射(仅有SRAM和ROM)的image文件,可以仅使用链接器命令行选项或scatter文件来指定内存映射。下图显示了一个简单的内存映射:
2)对于具有复杂内存映射(具有DRAM、SRAM、ROM2、ROM1等)的image文件,不能仅使用链接器命令行选项指定内存映射,需要使用scatter文件。下图显示了一个复杂的内存映射:
3分散加载文件说明
分散加载文件(scatter file)是一个文本文件,它的作用是可以用于描述 ARM 链接器生成映像文件所需要的信息。如果不使用分散加载文件来指定,那么 ARM 链接器会按照默认的方式来生成映像文件。Keil的分散加载主要是通过 .sct 文件实现的,链接器根据 .sct 文件的配置分配各个段区地址,生成分散加载代码。
编写分散加载文件中可以指定下列信息:
1)各个加载域的加载起始地址、最大尺寸和属性。
2)各个加载域中包含的输出段。
3)各个运行域的运行起始地址、最大尺寸、存储访问特性和属性。
4)各个运行域中包含的输入段。
一个Scatter文件包含若干个加载域,一个加载域包含若干个输出段,一个输出段由若干个具有相同属性的输入段组成。
4分散加载文件语法
Scatter文件是一个文本文件,使用BNF语法来描述ARM链接器生成映像文件时所需要的信息。
BNF符号与语法:
" :由双引号标识的符号保持其字面原意,如A”+”B表示A+B。
A ::= B :定义A为B。
[A] :用来表示可选部分,如A[B]C表示ABC或AC。
A+ :用来表示A可以重复任意次,如A+表示A,AA,AAA,......
A* :同A+。
A | B :用来表示选择其一,不能全选。如A|B表示A或者B。
(AB) :表示一个整体,通常其他符号一起使用,如(AB)+(C|D)表示ABC,ABD,ABABC,ABABD,......
一个Scatter文件包含一个或多个加载区域,每个加载区域可以包含一个或多个执行区域。下图显示了典型的Scatter文件的组成结构:
4.1 加载域描述
加载域可以包含一个或多个执行域。
加载域描述的语法如下:
1)load_region_name:命名加载区域。你可以使用带引号的名字。只有在使用任何与区域相关的链接器定义的符号时,该名称才区分大小写。
2)base_address:指定区域内对象的链接地址。base_address必须满足加载区域的对齐约束。
3)+offset:描述基址,该基址在前面的加载区域的末尾以外偏移字段。偏移量的值必须是0取4的模。如果这是第一个加载区域,那么+offset表示基址从零开始偏移字段。如果使用+offset,则加载区域可能会从前一个加载区域继承某些属性。
4)attribute_list:指定加载区域内容的属性。
5)max_size:指定加载区域的最大大小。这是在进行任何解压缩或零初始化之前加载区域的大小。如果指定了可选的max_size值,那么如果分配给该区域的字段超过max_size, armlink将生成一个错误。
6)execution_region_description:指定执行区域的名称、地址和内容。
4.2 执行域描述
执行域指定在运行时将输入段放置在目标内存中的位置。
执行域描述的语法如下:
1)exec_region_name:命名执行区域。你可以使用带引号的名字。只有在使用任何与区域相关的链接器定义的符号时,该名称才区分大小写。
2)base_address:指定区域内对象的链接地址。Base_address必须与字对齐。
注意:在执行区域上使用ALIGN会导致加载地址和执行地址对齐。
+offset:描述一个基址,该基址在前面执行区域的末尾以外偏移字段。偏移量的值必须是0取4的模。如果这是加载区的第一个执行区,则+offset表示基址在包含加载区的基址之后开始偏移字段。如果使用+offset,则执行区域可能会从父加载区域继承某些属性,或者从同一加载区域内的前一个执行区域继承某些属性。
4)attribute_list:指定执行区域内容的属性。
5)max_size:对于标记为EMPTY或FILL的执行区域,max_size值被解释为该区域的长度。否则,max_size值将被解释为执行区域的最大大小。
6)-length:只能与EMPTY一起使用,表示在内存中增长的堆栈。如果长度为负值,则base_address被视为该区域的结束地址。
7)input_section_description:指定输入段的内容。
4.3 输入段描述
输入段描述指定将哪些输入段加载到执行区域。
输入段描述的语法是:
1)module_select_pattern:
一种由文本构成的模式。当module_select_pattern匹配以下选项之一时,输入段匹配模块选择器模式:
包含该段的目标文件的名称。
库成员的名称(不带前导路径名)。
提取部分的库的全名(包括路径名)。如果名称包含空格,请使用通配符以简化搜索。
例如,使用*libname来匹配C:\lib dir\libname.lib。
通配符 * 匹配零个或多个字符,? 匹配任意单个字符。匹配不区分大小写,即使在文件命名区分大小写的主机上也是如此。使用 *.o 匹配所有对象,使用 * 来匹配所有的目标文件和库。可以使用带引号的文件名,例如”file one.o”。
在一个Scatter文件中不能有两个 * 选择器。但是可以使用两个修改过的选择器,例如*A和*B,并且可以将. any选择器与*模块选择器一起使用。*模块选择器的优先级高于.any。如果文件中包含*选择器的部分被删除,则. any选择器将变为活动的。
2)input_section_attr:
与输入部分属性匹配的属性选择器。每个input_section_attr后面跟着一个+。选择器不区分大小写,可以识别以下选择器:
RO-CODE
RO-DATA
RO,同时选择RO-CODE和RO-DATA
RW-DATA
RW-CODE
RW,同时选择RW-CODE和RW-DATA
XO
ZI
ENTRY,包含入口点的部分。
可以识别以下同义词:
CODE代表RO-CODE
CONST代表RO-DATA
TEXT代表RO
DATA代表RW
BSS代表ZI
可以识别以下伪属性:
FIRST
LAST
如果放置顺序很重要,则使用FIRST和LAST标记执行区域中的第一部分和最后一部分。例如,如果特定的输入部分必须在区域中位于第一个,并且包含校验和的输入部分必须位于最后。
FIRST和LAST必须不违反基本属性排序顺序。例如,FIRST RW放在任何只读代码或只读数据之后。
一个执行区域只能有一个FIRST或一个LAST属性,并且它必须遵循一个input_section_selector。例如:
*(section, +FIRST) 这种模式是正确的。
*(+FIRST, section) 此模式不正确,并产生错误消息。
3)input_section_pattern:
一种模式,不区分大小写,与输入段名匹配。它是由文字构成的。通配符 * 匹配0个或多个字符,而 ? 匹配任何单个字符。可以使用带引号的输入段名。
如果使用多个input_section_pattern,请确保在不同的执行区域中没有重复的模式,以避免歧义错误。
4)input_section_type:
与输入段类型进行比较的数字。支持十进制或十六进制。
5)input_symbol_pattern:
可以通过该段定义的全局符号名选择输入段。全局名称能够使你从部分链接的对象中选择具有相同名称的单个段。
6)section_properties:
section属性可以是+FIRST、+LAST和OVERALIGN值。OVERALIGN的值必须是2的正幂,且必须大于或等于4。
5如何打开.sct文件
在Options for Targets->Linker界面,Keil默认选择了“Use Memory Layout from Target Dialog”,勾掉复选框里面的对号,就可以使用自己定义的分散加载文件。
6练习
根据前面介绍的语法编辑 .sct文件,将函数和数据放到指定地址:
1)在LR_ROM加载域中定义2个执行域RW_RAM1、RW_RAM2:
RW_RAM1基地址为0x20001000,域大小为0x400,将TEST_FUNCTION_ADDR段最先加载到本域的起始地址。
RW_RAM2基地址为0x20001400,域大小为0x400,将TEST_DATA_ADDR段最先加载到本域的起始地址。
2)使用__attribute__((section("section_name"))) 定义函数和数据如下:
(表示将函数或数据放入指定名为"section_name"的段)
3)调用上述函数和数据:
编译后查看map文件中内存映射部分:
TEST_FUNCTION_ADDR段对应的执行域基地址为0x20001000,TEST_DATA_ADDR段对应的执行域基地址为0x20001400,和在Scatter文件定义一致,即将函数和数据放到了指定地址。
7小结
分散加载文件(scatter file)是一个文本文件,用于描述 ARM 链接器生成映像文件所需要的信息,在一些应用场景中嵌入式系统可能会使用分散加载。本章节简要介绍了分散加载文件的基本概念和语法,旨在对分散加载文件有初步认识,具体内容可以参考官方文档或查阅资料进行详细了解。
- |
- +1 赞 0
- 收藏
- 评论 0
本文由杰西啊杰西转载自灵动MM32MCU公众号,原文标题为:灵动微课堂 (第278讲)|Keil分散加载文件浅析,本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。
相关推荐
灵动微电子MM32F0160系列MCU FlexCAN-FD通信应用指南
MM32F0160系列MCU具有一个 FlexCAN 模块,该模块遵循 ISO 11898-1 标准、 CAN FD 和 CAN 2.0B 协议规范,不仅兼容传统CAN,还支持CAN FD模式。本章节初步学习使用MM32F0160 FlexCAN-FD接口实现CAN FD通信,相关例程参考灵动官网的LibSamples或在此基础上修改。
如何给Keil IAR等IDE以及jlink添加云途MCU信息?
由于不同厂牌以及不同型号的MCU都有其特定的架构、外设、寄存器配置等特性,故在使用Keil、IAR等集成开发环境(IDE)进行嵌入式系统开发时,为了使IDE正确地编译代码、配置项目设置以及进行调试。需要添加这些信息到指定的IDE环境中。本文以添加云途MCU YTM32B1LE0的设备信息为例进行说明。
使用灵动MM32F5270 MCU UART配置实现LIN通信
本文主要简述MM32F5270 UART是如何实现LIN通信的。从LIN驱动程序、 主机程序、从机程序和验证等方面来讲代码实现。
CPU和MCU的差异
在现代计算机和嵌入式系统中,CPU(中央处理器)和MCU(单片微型计算机)是两种关键的处理器类型,各自在不同的应用场景中发挥着重要作用。虽然它们都是处理器,但它们的设计和功能有着显著的差异。
SILICON LABS采用能量收集技术为嵌入式系统设计永续供电
许多无法连接市电的嵌入式系统通常会采用电池供电,但当电池电量用完时,更换电池的维护成本相对较高,并造成相当多的困扰,若能通过能量收集技术来为系统永续供电,便可解决这个问题。本文将为您介绍如何利用能量收集技术来建立永久运行的嵌入式系统,以及由Silicon Labs(芯科科技)推出的相关解决方案。
【IC】灵动发布全新入门级32位MCU MM32G0001系列,内置时钟全温度范围内偏差不超过±2%
灵动股份推出全新超值型MM32G0001系列MCU。2023年初,灵动首次发布了其主打高性价比的MM32G系列,目前已陆续推出了G0140,G0160和G5330系列产品。为进一步丰富MM32G系列产品组合,灵动和上下游合作伙伴通力合作,打造出全新入门级超值型MM32G0001系列MCU。
【经验】灵动MindSDK搭建Keil MDK开发环境指南
本文介绍基于Windows操作系统构建嵌入式系统开发环境过程中需要使用的主要软件Keil MDK,并对一些需要特别关注的要点重点说明。Keil MDK是灵动官方的软件开发平台MindSDK支持的主要编译工具之一。
【IC】灵动微电子高性能通用32位MCU产品MM32H5480荣获“2024年度硬核MCU芯片奖”
近日,第六届硬核芯生态大会在深圳举办,同期2024年度硬核中国芯获奖榜单正式发布。作为国内领先的本土通用32位MCU产品及解决方案供应商,MindMotion灵动微电子凭借高性能产品MM32H5480斩获“2024年度硬核MCU芯片奖”。
灵动发布全新MM32F0160系列MCU,72MHz主频,支持1路高达12.5 Mbps的I3C从机接口
灵动股份发布全新MM32F0160 系列 MCU,其搭载72MHz Arm® Cortex-M0处理器,内置128KB Flash,16KB RAM,配备高速ADC、USB、CAN-FD、I3C等丰富的模拟和通信资源,适用于工业物联网设备、PC外设、电子门锁、医疗和保健设备、个人手持设备、游戏娱乐等多种应用场景。
灵动MM32SPIN080C系列MCU,优化强排式热水器的高效热交换与智能控制
灵动微MM32SPIN080C系列微控制器,结合其高效电机控制和多模保护特性,为强排式热水器提供了一个低成本、高效率且具备多重保护的智能控制解决方案,优化热交换效率和使用安全性。
灵动微电子扎根张江造“芯”,打造本土32位MCU知名品牌
灵动微电子成立于2011年,2016年进军MCU市场,2019年积极向工业、大家电、汽车等领域发力,目前已涵盖消费电子、电机与电源、家电、汽车、计算机与通信、工业控制等应用领域,客户群体包括飞利浦、小米、汇川、海尔、海信、美的等,是中国本土领先的通用32位MCU 产品及解决方案供应商。
【技术】MCU芯片的分类及与MPU、SoC的区别
MCU是基于CPU发展起来的主控芯片,与之类似的MPU和SoC是CPU应用于高性能计算领域的产品。MCU芯片应用场景非常广泛,比如可应用在校园卡、身份证、家用电器以及红绿灯等,重要性丝毫不输CPU。
【经验】基于灵动微MM32L0130系列MCU的低功耗电子时钟设计指南
MM32L0130作为灵动微电子推出的一款低功耗芯片,内置多种省电工作模式保证低功耗应用的要求。本文通过讲述灵动微电子MM32L0130系列MCU PWR电源控制模式,以及SLCD 和RTC外设配置,实现低功耗应用场景。
基于MM32F5270 MCU初步学习移植FreeRTOS
FreeRTOS是一个RTOS类的嵌入式实时操作系统,具有源码公开、可移植、可裁减、调度策略灵活的特点,可以方便地移植到各种单片机上运行。本系列微课堂基于MM32F5270 MCU初步学习使用FreeRTOS开发。
电子商城
现货市场
服务
可定制显示屏的尺寸0.96”~15.6”,分辨率80*160~3840*2160,TN/IPS视角,支持RGB、MCU、SPI、MIPI、LVDS、HDMI接口,配套定制玻璃、背光、FPCA/PCBA。
最小起订量: 1000 提交需求>
可烧录IC封装SOP/MSOP/SSOP/TSOP/TSSOP/PLCC/QFP/QFN/MLP/MLF/BGA/CSP/SOT/DFN;IC包装Tray/Tube/Tape;IC厂商不限,交期1-3天。支持IC测试(FT/SLT),管装、托盘装、卷带装包装转换,IC打印标记加工。
最小起订量: 1pcs 提交需求>
登录 | 立即注册
提交评论