链接脚本语言(LSL)

为了充分利用链接器,您可以编写一个脚本,其中包含有关目标处理器体系结构和定位信息的信息。该脚本的语言称为链接器脚本语言(LSL)。本章首先介绍LSL文件的结构。下一节包含LSL语法的摘要。在其余部分中,将解释链接器脚本语言的语义。

TASKING连接器是一个独立于目标的连接器/定位器,它可以同时连接和定位目标板上所有可用内核的所有程序。目标板可能具有任意的复杂性。一个简单的目标板可能包含一个标准处理器和一些执行一个任务的外部存储器。复杂的目标板可能包含多个标准处理器和dsp,并结合FPGA中加载的可配置ip核。每个核可以执行不同的程序,外部存储器可以由多个核共享。

LSL有两个目的。首先,它使您能够指定特定目标板和安装在板上的核心的特性(连接器感兴趣的特性)。其次,它使您能够指定节应该如何在内存中定位。

一、 链接器脚本文件的结构

Structure of a Linker Script File 

一个脚本文件由几个定义组成。定义可以以任何顺序出现。

体系结构定义(必需的)

本质上,体系结构定义描述了链接器应该如何将给定类型的核心的逻辑地址转换为物理地址。如果内核支持多个地址空间,那么对于每个空间,链接器必须知道如何执行这种转换。在这种情况下,物理地址是给定内部或外部总线上的偏移量。此外,体系结构定义包含了诸如(硬件)堆栈和中断向量表之类的项目信息。

该规范通常由Altium编写。Altium在include.lsl目录中提供LSL文件。除非您也修改了核心的硬件体系结构,否则不应该更改LSL文件的体系结构定义。如果LSL文件描述的是多核系统,那么体系结构定义必须适用于每种不同类型的核。

派生定义

派生定义描述了内部(片上)总线和存储系统的配置。基本上,它告诉链接器如何将架构定义中指定的总线上的偏移量转换为内部内存中的偏移量。除了一个或多个内核外,微控制器和dsp通常还有内部存储器和I/O子系统。这种芯片的设计称为衍生芯片。

Altium提供了支持的派生函数的LSL描述,以及“SFR文件”,这些文件提供了从C和汇编程序轻松访问l/O子系统中的寄存器的方法。当您构建ASIC或使用不受任务工具支持的派生产品时,您可能必须编写派生产品定义。

当您想要使用相同类型的多个核心时,您必须在派生定义中实例化这些核心,因为链接器只会为未使用的体系结构自动实例化单个核心。

处理器定义

处理器定义描述一个派生的实例。通常,处理器定义只实例化一个衍生物(单核处理器)。包含具有相同(同构)或不同(异构)体系结构的多个内核的处理器也可以通过在单独的处理器定义中实例化相同或不同类型的多个衍生品来描述。

内存和总线定义(可选)

内存和总线定义在派生定义的上下文中使用,以指定内部内存和片上总线。在版本规范的上下文中,存储器和总线定义用于定义外部(片外)存储器和总线。给定上述定义,连接器可以将逻辑地址转换为片内或片外存储器设备的偏移量。

版本规格

处理器定义、存储器和总线定义一起构成一个版本规范。LSL提供了语言结构来方便地描述单核和异构或同构的多核系统。该板规范描述了您的目标板的系统总线、内存设备、I/O子系统和链接器感兴趣的核心的所有特性。根据版本规格中提供的信息,链接器为每个核心提供链接器:

                        将逻辑地址转换为内存设备中的偏移量

                        在物理内存中定位节在定位时

                        维护整个系统内已使用和空闲物理内存的总体视图

Section布局定义(可选)

Section布局定义使您能够精确控制输入节的位置。提供的功能包括:能够将部分放置在给定的加载地址或运行时地址,以给定的顺序放置部分,以及覆盖代码和/或数据部分。在调用链接器时,在命令行上指定将在给定核心上运行的任务的对象文件(节)。链接器将同时链接并定位所有任务的所有部分。从节布局定义中,链接器可以推断出给定节在内存中的位置,根据电路板规格,连接器可以在定位节时推断出(仍然)可用的物理内存。

链接器脚本文件的框架

architecture architecture_name
{
 // Specification core architecture
}
derivative derivative_name
{
 // Derivative definition
}
processor processor_name
{
 // Processor definition
}
memory and/or bus definitions
section_layout space_name
{
 // section placement statements
}


二、 链接器脚本语言的语法

Syntax of the Linker Script Language 

LSL文档以UTF-8编码的文件形式存储,扩展名为.lsl。在处理LSL文件之前,链接器使用标准对其进行预处理C预处理器。接下来,链接器使用扫描器解析器解释LSL文件。最后,链接器使用在LSL文件中找到的信息来指导定位过程。

 
1.预处理

Preprocessing 

当链接器加载LSL文件时,链接器首先用c风格的预处理器处理它。因此,它会剥离C和C++注释。以#字符开头的行作为预处理器的命令。您可以使用标准的ISO C99预处理器指令,包括:

                                #include "file"
                                #include <file>

此时在LSL文件中预处理并包含文件文件。例如:

#include "arch.lsl"
预处理并包含文件arch.lsl在LSL文件中。
#if condition
#else
#endif
如果条件的计算结果为非零值,则复制以下行,直到#else或#endif命令,如果存在,则跳过#else和#endif之间的行。如果条件的计算结果为零,则跳过到#else命令的行,如果没有#else,则跳过到#endif命令的行,并复制#else和#endif命令之间的行。
#ifdef identifier
#else
#endif
与#if相同,但以defined(identifier)作为条件。
#error text
对给定的消息(可选)导致致命错误。

 
2. 词汇语法

Lexical Syntax 

下面的词汇用于描述链接器脚本语言的语法:

A  :: = B        A被定义为B

A:: = BC       A定义为B和C,B后面跟着C

A:: = B | C    A被定义为B或C

< B > 0|1     0或1次出现B

< B > > = 0   B的出现次数为零

< B > > = 1   B的多次出现标识符

IDENTIFIER       以'a'-'z', 'a'-'z'或'_'开头的字符序列。后字符也可以是数字和点。

STRING             不以\n、\r或\t开头的字符序列

DQSTRING        “STRING ”(带双引号的字符串)
OCT_NUM         八进制数,从0开始(06,045)

DEC_NUM         十进制数,不为零(14,1024)= DEC_NUM开头

HEX_NUM          十进制数,不为零(14,1024)= DEC_NUM开头

OCT_NUM、DEC_NUM和HEX_NUM后面可以跟k (kilo)、M (mega)或G (giga)。

粗体字符是字面上出现的字符。斜体中的单词是在同一部分或其他部分中定义的高阶术语。要在LSL文件中编写注释,您可以使用C风格的'/* */'或c++风格的'//'。


3. 标识符和标签

Identifiers and Tags 

标记是可以添加到语句中的任意文本。

  
4. 表达式

Expressions   

本节中的表达式和操作符与ISO c中的相同。


5.内置函数

Built-in Functions 

您引用的每个空间、总线、内存、段或组都必须在LSL文件中定义。

带group或sect参数的addressof()和sizeof()函数只能在赋值操作的右侧使用。

带有mem参数的sizeof()函数可以在section布局的任何地方使用。

checksum()函数只能在struct语句中使用。

您可以在表达式中使用以下内置函数。所有函数都返回一个数值。64位有符号整数。

absolute()
int absolute( expr )
将expr的值转换为正整数。
absolute( "labelA"-"labelB" )
addressof()
int addressof( addr_id )
返回addr_id的偏移量,它是在section布局的地址空间中的命名section、组或内存。如果引用的对象是组或内存,则必须在LSL文件中定义它。获取名称为asect的节的偏移量:
addressof( sect: "asect")
这个函数只在赋值和struct语句中起作用。
checksum()
int checksum( checksum_algo , expr , expr )
返回连续地址范围内计算的校验和。第一个参数指定如何计算校验和(见下文),第二个参数是一个表达式,表示范围的开始地址,而第三个参数表示结束地址(不包含)。结束地址表达式的值必须严格大于开始地址的值(即校验和地址范围的大小必须至少为一个MAU)。范围内的每个地址必须指向一个有效的内存位置。地址范围内未被段占用的内存位置用零填充。目前唯一支持的校验和算法(checksum_algo)是crc32w。该算法使用循环冗余校验与“CRC-32”多项式OxEDB88320计算校验和。输入范围按4字节字处理。如果目标架构是小端序的,那么这4个字节将以相反的顺序传递给校验和算法。对于大端目标,这个校验和算法等同于常规的按字节的CRC-32实现。4个mau上的起始地址和结束地址值必须对齐。当在MAU大小不等于8的地址空间中使用时,此校验和算法的行为是未定义的。
checksum( crc32w,
                   __BMHD_ALIGN( addressof( mem:foo ), -4 ),
                   __BMHD_ALIGN( addressof( mem:foo ) + sizeof( mem:foo ), 4 ) )
这个函数只在struct语句中起作用。

exists()
int exists( section_name )
如果section section_name存在于一个或多个object文件中,该函数返回1,否则返回0。如果该节不存在于输入对象文件中,而是由LSL生成,则此函数的结果是未定义的。要检查小节mysection是否存在于指定给链接器的某个object文件中:
exists( "mysection" )
max()
int max( expr , expr )
返回值最大的表达式的值。要获得两个符号的最大值:
max( "sym1" , "sym2")
min()
int min( expr , expr )
返回具有最小值的表达式的值。要得到两个符号的最低值:
min( "sym1" , "sym2")
sizeof()
int sizeof( size_id )
返回标识符引用的对象(组、段或内存)的大小。获取section" asection"的大小:
sizeof( sect: "asection" )

group和sect参数只适用于赋值和struct语句。mem参数可以在section布局的任何地方使用。如果引用的对象是组或内存,则必须在LSL文件中定义它。

  


6.链接器脚本文件中的LSL定义

LSL Definitions in the Linker Script File 

•LSL文件中必须至少有一个architecture_definition。

mem_def ::= memory mem_name < tag_attr > 0|1 { < mem_descr ; > >=0 }

mem_def用mem_name作为惟一名称来定义内存。

mem_def只包含一条类型语句。

mem_def只包含一条mau语句(非零大小)。

mem_def只包含一个大小的语句。

mem_def包含零或一个优先级(或速度)语句(如果没有,默认值为1)。

mem_def包含零或一个exec_priority语句。

mem_def包含零或一个填充语句。

mem_def包含零或一条write_unit语句。

mem_def至少包含一个映射

总线自定义语句使用给定的总线名称将总线定义为内核体系结构中的唯一名称。

mau和width语句在bus_descr中只出现一次。width的默认值是mau的大小。

总线宽度必须是总线MAU大小的整数倍。

MAU大小必须非零。

总线只能在目标总线上有一个映射(通过dest = bus:))。

map_descr至少需要size和dest语句。

map_descr包含零条或一条缓存语句。

map_descr包含零或一个优先级语句(如果没有,默认值为0)。

map_descr包含零或一个exec_priority语句。

每个map_descr只能出现一次。

您可以从单个源定义多个映射。

源范围或目的范围之间不允许有重叠。

如果src_dbits或dest_dbits语句不存在,如果源/目标是总线,则其值默认为宽度值,否则为mau大小。

保留语句只允许在为内存定义的映射中使用。

space_name指的是一个已定义的地址空间。

proc_name指的是一个已定义的处理器。

core_name指的是已定义的核心。

bus_name指的是已定义的总线。

允许使用以下映射(源到目标)

                • space => space
                • space => bus
                • bus => bus
                • memory => bus

对于地址范围,结束地址不是范围的一部分。

7. 内存和总线定义

Memory and Bus Definitions 

  
8. 架构定义

Architecture Definition 

 
9. 导数定义

Derivative Definition 

  
10. 处理器定义和版本规格

Processor Definition and Board Specification 

  
11. Section设置

Section Setup    


12. Section布局定义

Section Layout Definition    


13. 单板布局定义

Veneer Layout Definition 

  
三、表达式求值

Expression Evaluation 

  
四、架构定义的语义

Semantics of the Architecture Definition 

  
1. 定义架构

Defining an Architecture 

  
2.  定义内部总线

Defining Internal Buses 

  
3. 定义地址空间

Defining Address Spaces 

  
4. 映射

Mappings 

  
5. 定义MPU布局

Defining the MPU Layout 

  
五、导数定义的语义

Semantics of the Derivative Definition

    
1.定义导数

Defining a Derivative 

 
2.实例化核心架构

Instantiating Core Architectures 

 
3.定义内部存储器和总线

Defining Internal Memory and Buses 

  
六、版本规格的定义

Semantics of the Board Specification   

 
1. 定义处理器

Defining a Processor

    
2. 实例化衍生品

Instantiating Derivatives 

 
3.  定义外部存储器和总线

Defining External Memory and Buses

    
七、Section设置定义的语义

Semantics of the Section Setup Definition

    
1. 设置Section

Setting up a Section   


八、 Section布局定义的语义

Semantics of the Section Layout Definition 

  
1. 定义Section布局

Defining a Section Layout 

  
2. 创建和定位Section组

Creating and Locating Groups of Sections

    
3. 创建或修改特殊Section

Creating or Modifying Special Sections 

  

4. 创建符号

Creating Symbols


5.  条件组语句

Conditional Group Statements 

  
九、 单板布局定义的语义

Semantics of the Veneer Layout Definition 

  
1. 单板位置

Veneer Placement    

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值