TI J6 SPL 链接脚本u-boot-spl.lds分析

本文详细解析了U-Boot SPL的链接脚本u-boot-spl.lds,阐述了如何通过该脚本指定SPL代码在SRAM中的布局,并介绍了关键的内存配置参数和段分配策略。
u-boot-spl.lds链接脚本文件,为编译器在编译过程中,依照该链接脚本,指定了SPL代码在SRAM中的链接地址。在嵌入式开发环境中,SRAM空间极其有限的时候,分析lds链接脚本,了解SPL代码在SRAM中的布局,尤为重要,当SRAM空间略微不足的,我们可以通过修改链接脚本加以适当调整。
分析lds脚本,请结合该链接脚本编译后生成的u-boot-spl.map文件同步对比分析。该文件就是依照该链接脚本将SPL所有代码链接之后的map文件。可见就是按照lds文件指定的地址存放。
Linker script and memory map
.text 0x0000000040300000 0xf510
0x0000000040300000 __start = .
*(.vectors)
.vectors 0x0000000040300000 0x60 arch/arm/lib/built-in.o //可知最开始的代码路径
0x0000000040300000 _start
0x0000000040300020 _undefined_instruction
0x0000000040300024 _software_interrupt
0x0000000040300028 _prefetch_abort
0x000000004030002c _data_abort
0x0000000040300030 _not_used
0x0000000040300034 _irq
0x0000000040300038 _fiq

下面以TI J6中uboot中额u-boot-spl.lds(编译后)文件分析:
MEMORY { .sram : ORIGIN = 0x40300000, LENGTH = ((0x4037E000 - 0x00000400) - 0x40300000) }
MEMORY { .sdram : ORIGIN = 0x80a00000, LENGTH = 0x80000 }
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
.text :
{
__start = .;
*(.vectors)
arch/arm/cpu/armv7/start.o (.text*)
*(.text*)
} >.sram
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
. = ALIGN(4);
.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
} >.sram
. = ALIGN(4);
__image_copy_end = .;
.end :
{
*(.__end)
}
.bss :
{
. = ALIGN(4);
__bss_start = .;
*(.bss*)
. = ALIGN(4);
__bss_end = .;
} >.sdram
}

0.
MEMORY { .sram : ORIGIN = 0x40300000, LENGTH = ((0x4037E000 - 0x00000400) - 0x40300000) }
MEMORY { .sdram : ORIGIN = 0x80a00000, LENGTH = 0x80000 }
ORIGIN 指定J6内部SRAM的内存区域起始地址为0x40300000 ,LENGTH指定内存区域长度
1.
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")/*指定输出可执行文件是elf格式,32位ARM指令,小端*/OUTPUT_ARCH(arm)/*指定输出可执行文件的平台为ARM*/

2.
ENTRY(_start)指定了该spl程序的入口地址为_start
关于入口点:
在程序运行时第一个被执行的指令称为“入口点”
有多种不同的方法来设置入口点,连接器会通过按顺序尝试以下的方法来设置入口点,如果成功了就会停止。
1)'-e' 入口命令行选项
2)连接脚本中的‘ENTRY(SYMBOL)’
3)如果定义了start,就使用start的值
4)如果存在,就是用‘.text’的首地址
5)地址'0'

3..text 定义text段,text段代表可执行程序的代码段,(接口函数)
.text :
{
__start = .; //定义__start标号的地址为当前地址
*(.vectors) //放所有链接目标文件的vectors段
arch/arm/cpu/armv7/start.o (.text*) //放start.o的代码段?
*(.text*) //放所有输入文件可执行程序的代码段
} >.sram //指定是sram,即J6内部SRAM

4.调整定位到4字节对齐处 . = ALIGN(4);
5.rodata 只读数据段,通常存放只读数据,如常量,常量字符串和常量数据等
.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
6. .data 数据段,通常代表数组,变量,结构体等。
data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
7.u_boot_list段,通常u-boot cmd会在u_boot_list段
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
7.__image_copy_end 整个image结束的地址
在u-boot-spl.map中可知:
0x000000004031b360 __image_copy_end
0x0000000040300000 _start
可知长度为:0x0001b360

在编译出的MLO(spl+header)的最后8个字节包含了该信息:
60 B3 01 00 00 00 30 40 : 大小端表示0x40300000 和0x0001B360
<think>根据用户的问题,用户希望理解Makefile代码片段 `$(splobj)u-boot-spl-16k.bin: $(splobj)u-boot-spl.bin; cat $(splobj)u-boot-spl.bin > $@` 的含义。 分析该Makefile规则: 1. 目标(target):`$(splobj)u-boot-spl-16k.bin` 2. 依赖(prerequisite):`$(splobj)u-boot-spl.bin` 3. 命令(command):`cat $(splobj)u-boot-spl.bin > $@` 其中: - `$(splobj)` 是一个变量,代表生成文件的目录路径。 - `$@` 在Makefile规则中代表目标文件名,即`$(splobj)u-boot-spl-16k.bin`。 该规则的含义: 当需要生成目标文件 `u-boot-spl-16k.bin` 时,它依赖于 `u-boot-spl.bin` 文件。生成规则是通过 `cat` 命令将依赖文件 `u-boot-spl.bin` 的内容输出(重定向)到目标文件 `u-boot-spl-16k.bin` 中。注意,这里没有对内容进行修改,只是简单的复制。 但是,从文件名来看,目标文件名为 `u-boot-spl-16k.bin`,这通常暗示该文件大小为16KB。然而,当前规则只是简单复制,所以要求输入的 `u-boot-spl.bin` 文件大小必须已经是16KB(或者至少是符合要求的)。如果原始文件大小不足16KB,这样复制可能会导致问题,因为通常SPL(Secondary Program Loader)需要精确的大小(比如16KB)来烧写到特定的启动区域。 结合引用[1]和引用[2]的内容: 引用[1]中使用了`truncate`命令来将文件调整为16KB(`truncate $(objtree)/tmp.bin -c -s 16K`),然后再与u-boot.bin合并。引用[2]中则直接使用了一个名为`u-boot-spl-16k.bin`的文件,说明该文件已经是16KB大小。 因此,可以推断:在用户提供的规则中,输入文件`u-boot-spl.bin`可能已经被构建为16KB大小(例如通过其他规则使用`truncate`或其他方式调整大小),或者该规则仅用于重命名(但这种情况较少见,因为内容相同而文件名不同,通常是为了满足后续步骤的要求)。 所以,这个规则的作用是将`u-boot-spl.bin`文件复制一份并命名为`u-boot-spl-16k.bin`。它假设`u-boot-spl.bin`已经具有正确的16KB大小。 如果用户需要确保大小,可能还需要在规则中添加调整文件大小的命令(如`truncate`),但当前规则并没有这样做。 总结: 该规则定义了一个简单的文件复制操作,将`u-boot-spl.bin`复制为`u-boot-spl-16k.bin`,依赖关系确保在`u-boot-spl.bin`更新时重新复制。 注意事项: 如果`u-boot-spl.bin`的大小不是16KB,那么复制得到的`u-boot-spl-16k.bin`也不会是16KB(除非原始文件恰好16KB)。因此,这个规则通常是在确保`u-boot-spl.bin`已经是16KB的前提下使用。 为了更严谨,我们可以参考引用[1]中的做法,先调整文件大小再复制。但是当前规则没有这一步,所以用户需要检查构建系统中是否有其他规则确保`u-boot-spl.bin`的大小为16KB。 现在,根据用户要求,生成相关问题。 </think> ### Makefile规则解释 您提供的Makefile规则 `$(splobj)u-boot-spl-16k.bin: $(splobj)u-boot-spl.bin; cat $(splobj)u-boot-spl.bin > $@` 含义如下: 1. **目标文件**: `$(splobj)u-boot-spl-16k.bin` 是最终要生成的文件名。其中: - `$(splobj)` 是变量,表示SPL(Secondary Program Loader)的构建目录路径 - `u-boot-spl-16k.bin` 是目标文件名,表明这是大小为 **16KB** 的SPL镜像文件[^3] 2. **依赖关系**: `$(splobj)u-boot-spl.bin` 是生成目标所需的输入文件。该文件是标准的SPL二进制镜像(通常未做大小限制)[^1] 3. **构建命令**: `cat $(splobj)u-boot-spl.bin > $@` 执行以下操作: - 使用 `cat` 命令读取依赖文件 `u-boot-spl.bin` 的内容 - 通过重定向 `>` 将内容输出到目标文件 `$@`(`$@` 是Makefile自动变量,代表当前目标文件名) - **关键作用**:直接复制二进制文件内容,但要求输入文件必须是 **精确的16KB**(否则会破坏镜像结构)[^2] ### 典型应用场景 此规则常用于嵌入式系统启动流程: 1. 先编译生成标准SPL镜像 `u-boot-spl.bin` 2. **通过此规则创建固定16KB的SPL镜像**,用于NAND Flash等需要精确分区大小的存储设备 3. 最终与主U-Boot镜像拼接,如引用[2]所示: ```makefile $(U_BOOT_NAND): $(NAND_SPL) $(obj)u-boot.bin cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin > $@ ``` ### 注意事项 - **隐含要求**:输入文件 `u-boot-spl.bin` 必须**严格等于16KB**,否则需使用 `truncate` 等工具调整大小(如引用[1]所示) - **目录依赖**:`$(splobj)` 变量需正确定义,通常通过顶层Makefile配置[^3] - **等价操作**:此规则等同于: ```makefile $(splobj)u-boot-spl-16k.bin: $(splobj)u-boot-spl.bin cp $< $@ # $< 表示第一个依赖文件 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值