前言:
眼前我们对“uboot spl 编译”大概比较重视,看官们都需要了解一些“uboot spl 编译”的相关知识。那么小编在网摘上收集了一些对于“uboot spl 编译””的相关资讯,希望咱们能喜欢,兄弟们一起来学习一下吧!比较杂,因为每天只发5篇,所以这一个相当于工作学习日志,记事本。各位勿怪,
BIC
BIC―――――位清除指令
指令格式:
BIC{cond}{S} Rd,Rn,operand2
BIC指令将Rn 的值与操作数operand2 的反码按位逻辑”与”,结果存放到目的寄存器Rd 中。指令示例:BIC R0,R0,#0x0F ;将R0最低4位清零,其余位不变。
6.
lr就是连接寄存器(Link Register, LR),在ARM体系结构中LR的特殊用途有两种:一是用来保存子程序返回地址;二是当异常发生时,LR中保存的值等于异常发生时PC的值减4(或者减2),因此在各种异常模式下可以根据LR的值返回到异常发生前的相应位置继续执行。
7.Program Counter程序计数器,用于指示当前将要执行的下一条机器指令的内存地址。在IBM PC计算机中所用的INTEL CPU中,它被称为 IP (Instruction Pointer指令指针)
8.adr r0, _start 得到的是_start的当前执行位置,由 pc+offset 决定的 得到有效地址
ldr r0, =_start 得到的是绝对的地址,链接时决定;
9.
bss段:
bss段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。
bss是英文Block Started by Symbol的简称。
bss段属于静态内存分配。
data段:
数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。
数据段属于静态内存分配。
text段:
代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。
这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读(某些架构也允许代码段为可写,即允许修改程序)。
在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
堆(heap):
堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。
当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);
当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。
栈(stack):
栈又称堆栈,是用户存放程序临时创建的局部变量,
也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。
除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。
由于栈的先进先出(FIFO)特点,所以栈特别方便用来保存/恢复调用现场。
从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。
一个程序本质上都是由 bss段、data段、text段三个组成的。
这样的概念,不知道最初来源于哪里的规定,但在当前的计算机程序设计中是很重要的一个基本概念。
而且在嵌入式系统的设计中也非常重要,牵涉到嵌入式系统运行时的内存大小分配,存储单元占用空间大小的问题。
在采用段式内存管理的架构中(比如intel的80x86系统),bss段通常是指用来存放程序中未初始化的全局变量的一块内存区域,
一般在初始化时bss 段部分将会清零。bss段属于静态内存分配,即程序一开始就将其清零了。
比如,在C语言之类的程序编译完成之后,已初始化的全局变量保存在.data 段中,未初始化的全局变量保存在.bss 段中。
text和data段都在可执行文件中(在嵌入式系统里一般是固化在镜像文件中),由系统从可执行文件中加载;
而bss段不在可执行文件中,由系统初始化。
【例】
两个小程序如下:
程序1:
int ar[30000];void main(){ ......}
程序2:
int ar[300000] = {1, 2, 3, 4, 5, 6 };void main(){ ......}
发现程序2编译之后所得的.exe文件比程序1的要大得多。当下甚为不解,于是手工编译了一下,并使用了/FAs编译选项来查看了一下其各自的.asm,
发现在程序1.asm中ar的定义如下:
_BSS SEGMENT
?ar@@3PAHA DD 0493e0H DUP (?) ; ar
_BSS ENDS
而在程序2.asm中,ar被定义为:
_DATA SEGMENT
?ar@@3PAHA DD 01H ; ar
DD 02H
DD 03H
ORG $+1199988
_DATA ENDS
区别很明显,一个位于.bss段,而另一个位于.data段,两者的区别在于:
全局的未初始化变量存在于.bss段中,具体体现为一个占位符;
全局的已初始化变量存于.data段中;
而函数内的自动变量都在栈上分配空间;
.bss是不占用.exe文件空间的,其内容由操作系统初始化(清零);
.data却需要占用,其内容由程序初始化。因此造成了上述情况。
bss段(未手动初始化的数据)并不给该段的数据分配空间,只是记录数据所需空间的大小;
bss段的大小从可执行文件中得到 ,然后链接器得到这个大小的内存块,紧跟在数据段后面。
data段(已手动初始化的数据)则为数据分配空间,数据保存在目标文件中;
data段包含经过初始化的全局变量以及它们的值。当这个内存区进入程序的地址空间后全部清零。
包含data段和bss段的整个区段此时通常称为数据区。
10、
1.uboot SPL架构简介
在uboot-2011之后的版本中多了一个叫SPL的架构,这个架构有什么用呢?在uboot-2011的/doc/README.spl文件有简单的介绍:
Generic SPL framework=====================Overview--------To unify all existing implementations for a secondary program loader (SPL)and to allow simply adding of new implementations this generic SPL frameworkhas been created. With this framework almost all source files for a boardcan be reused. No code duplication or symlinking is necessary anymore.为了统一所有现有实现第二段的程序加载程序(SPL)并允许简单地添加新的实现这个,一个通用SPL框架已创建。用这个框架板的几乎所有的源文件可以重用。没有代码重复或符号链接是必要的了。How it works------------There is a new directory TOPDIR/spl which contains only a Makefile.The object files are built separately for SPL and placed in this directory.The final binaries which are generated are u-boot-spl, u-boot-spl.bin andu-boot-spl.map.During the SPL build a variable named CONFIG_SPL_BUILD is exportedin the make environment and also appended to CPPFLAGS with -DCONFIG_SPL_BUILD.Source files can therefore be compiled for SPL with different settings.ARM-based boards have previously used the option CONFIG_PRELOADER for it.For example:ifeq ($(CONFIG_SPL_BUILD),y)COBJS-y += board_spl.oelseCOBJS-y += board.oendifCOBJS-$(CONFIG_SPL_BUILD) += foo.o#ifdef CONFIG_SPL_BUILD foo();#endifThe building of SPL images can be with:#define CONFIG_SPLBecause SPL images normally have a different text base, one have to beconfigured by defining CONFIG_SPL_TEXT_BASE. The linker script have to bedefined with CONFIG_SPL_LDSCRIPT.To support generic U-Boot libraries and drivers in the SPL binary one canoptionally define CONFIG_SPL_XXX_SUPPORT. Currently following optionsare supported:CONFIG_SPL_LIBCOMMON_SUPPORT (common/libcommon.o)CONFIG_SPL_LIBDISK_SUPPORT (disk/libdisk.o)CONFIG_SPL_I2C_SUPPORT (drivers/i2c/libi2c.o)CONFIG_SPL_GPIO_SUPPORT (drivers/gpio/libgpio.o)CONFIG_SPL_MMC_SUPPORT (drivers/mmc/libmmc.o)CONFIG_SPL_SERIAL_SUPPORT (drivers/serial/libserial.o)CONFIG_SPL_SPI_FLASH_SUPPORT (drivers/mtd/spi/libspi_flash.o)CONFIG_SPL_SPI_SUPPORT (drivers/spi/libspi.o)CONFIG_SPL_FAT_SUPPORT (fs/fat/libfat.o)CONFIG_SPL_LIBGENERIC_SUPPORT (lib/libgeneric.o)
移植过uboot的都知道,uboot的启动其实是分为BL0,BL1,BL2三个阶段的,即:ROM->SPL->uboot.img.而这个SPL架构将可以编译产生一个uboot-spl.bin。即BL1的代码。也就是说SPL结构其实做的工作就是uboot的BL1阶段的工作。
2.SPL结构是如何工作的
cd 进入spl目录,从编译文件看这个架构都包括了什么文件: 我们先来看该目录Makefile: 当CONFIG_SPL_BUILD := y driver下设备驱动和arch/arm与cup相关的东东将被编译。 CONFIG_SPL_BUILD := y export CONFIG_SPL_BUILD
include $(TOPDIR)/config.mk# We want the final binaries in this directoryobj := $(OBJTREE)/spl/ HAVE_VENDOR_COMMON_LIB := $(shell [ -f $(SRCTREE)/board/$(VENDOR)/common/Makefile ] \ && echo y || echo n)START := $(CPUDIR)/start.oLIBS-y += arch/$(ARCH)/lib/lib$(ARCH).oLIBS-y += $(CPUDIR)/lib$(CPU).oifdef SOCLIBS-y += $(CPUDIR)/$(SOC)/lib$(SOC).oendifLIBS-y += board/$(BOARDDIR)/lib$(BOARD).oLIBS-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/lib$(VENDOR).oLIBS-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/libcommon.oLIBS-$(CONFIG_SPL_LIBDISK_SUPPORT) += disk/libdisk.oLIBS-$(CONFIG_SPL_I2C_SUPPORT) += drivers/i2c/libi2c.oLIBS-$(CONFIG_SPL_GPIO_SUPPORT) += drivers/gpio/libgpio.oLIBS-$(CONFIG_SPL_MMC_SUPPORT) += drivers/mmc/libmmc.oLIBS-$(CONFIG_SPL_SERIAL_SUPPORT) += drivers/serial/libserial.oLIBS-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += drivers/mtd/spi/libspi_flash.oLIBS-$(CONFIG_SPL_SPI_SUPPORT) += drivers/spi/libspi.oLIBS-$(CONFIG_SPL_FAT_SUPPORT) += fs/fat/libfat.oLIBS-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/libgeneric.o
接下来是连接到一个脚本,u-boot-spl.lds
# Linker Script ifdef CONFIG_SPL_LDSCRIPT # need to strip off double quotes LDSCRIPT := $(addprefix $(SRCTREE)/,$(subst ",,$(CONFIG_SPL_LDSCRIPT))) endif ifeq ($(wildcard $(LDSCRIPT)),) LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-spl.lds endif ifeq ($(wildcard $(LDSCRIPT)),) LDSCRIPT := $(TOPDIR)/$(CPUDIR)/u-boot-spl.lds endif ifeq ($(wildcard $(LDSCRIPT)),) $(error could not find linker script) endif
在arm/cpu/armv7目录下找到u-boot-spl.lds这个连接脚本
MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\ LENGTH = CONFIG_SPL_MAX_SIZE }MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ LENGTH = CONFIG_SPL_BSS_MAX_SIZE }OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")OUTPUT_ARCH(arm)ENTRY(_start)SECTIONS{ .text : { __start = .; 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); __image_copy_end = .; _end = .; .bss : { . = ALIGN(4); __bss_start = .; *(.bss*) . = ALIGN(4); __bss_end__ = .; } >.sdram}
其实这个连接脚本最后连接到还是arch/arm/cpu/armv7/start.S,作为他的入口。
(reset) <arch/arm/cpu/armv7/start.S> (b lowlevel_init: arch/arm/cpu/armv7/lowlevel_init.S) (b _main) –> <arch/arm/lib/crt0.S> (bl board_init_f) –> <arch/arm/lib/spl.c> (board_init_r) –> <common/spl/spl.c> (jump_to_image_no_args去启动u-boot) 到此SPL的生命周期结束。
12/
.gd_t: global data数据结构定义,位于文件 include/asm-arm/global_data.h。其成员主要是一些全局的系统初始化参数。需要用到时用宏定义:DECLARE_GLOBAL_DATA_PTR,指定占用寄存器R8。
2.bd_t : board info数据结构定义,位于文件 include/asm-arm/u-boot.h。保存板子参数。
标签: #uboot spl 编译