/*说明:这个文件为说明文件,加入了伪注释代码,如果编译可能会出现问题。文 件位于http://hi.http://www.china-audit.com//yaozonggui,有批评或指正请联系yaozonggui@yeah.net, 希望能够向大家学习!*/ /*
start.s 是U-boot中最先运行的程序,也是处理器最运行的第一个外部代码。在AM335x 处理器内部还有一些出厂就已经烧写好的程序,位于片上ROM中,并且用硬件配置了启 动设备,开机自动运行完片上ROM的指令后就会自动运行启动设备(如nandflash)上的 程序。现在说的start.s是在启动设备上的第一段代码,通常位于U-boot/arch/arm/cpu /armv7。本文暂时仅仅对部分代码进行了简单分析,关于连接和脚本的知识有待进一步 学习。 */
#include
包含的头文件,第一个asm-offsets.h应该是U-boot/include/asm-offsets.h下的头文件, 非常短,列出来:
#ifndef DO_DEPS_ONLY
#include
#endif
这里面的generated/asm-offsets.h是不存在的,应该是由某个脚本产生的,应该就是顶层的 makefile产生的。可能涉及汇编的一些内存地址偏移量,暂时忽略。
第二个config.h在U-boot/linux,或者U-boot/arch/arm/include/asm,前者没有实际内容, 列出来:
#ifndef _LINUX_CONFIG_H #define _LINUX_CONFIG_H
/* #include
#endif
后者也很短,列出来:
#ifndef _ASM_CONFIG_H_ #define _ASM_CONFIG_H_
#define CONFIG_LMB
#define CONFIG_SYS_BOOT_RAMDISK_HIGH #endif
根据start.s是最开始的程序判断,应该不是前者,因为宏里涉及linux。那么在后者中,就定义了 两个宏,CONFIG_LMB,CONFIG_SYS_BOOT_RAMDISK_HIGH,可能在本文件中有用到。 version.h应该是U-boot/include下的,里面都是引入一些宏定义,还有就是类似前面的包含待产
生文件,那么也先不去管它。
后面两个宏定义也不存在,应该也是脚本产生,暂时不去管它。 */
.globl _start _start: b reset /*
这里对_start先做了一个声明,我们看看网上有一位前辈非常详细地讲解了这部分的内容: “.global Makes symbol visible to the linker
意思很简单,就是相当于C语言中的Extern,声明此变量,并且告诉链接器此变量是全局的,外部可 以访问
所以,你可以看到
u-boot-1.1.6_20100601\\opt\\EmbedSky\%u-boot-1.1.6\\board\\EmbedSky\%u-boot.lds 中,有用到此变量: ENTRY(_start)
即指定入口为_start,而由下面的_start的含义可以得知,_start就是整个start.S的最开始,即整个
uboot的代码的开始。”
很清楚了,这就是连接和方便调用的,而他说的“由下面_start的含义可知”在后面提到说在连接文
件连接的时候,将star.s连接在了程序的最开始的地方,这就是我们都说start.s是最开始的代码的
原因。
后面的_start: b reset代码起了一个作用,就是启动后跳转到reset标号所在的地方。这个标号在程 序后面。 */ ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq /*
这就是大名鼎鼎的中断向量。每个指令占4字节,而中断向量在手册的initialization一节有讲到,处理
器在探测到中断时,会根据中断类型自动地跳转到相应的地址执行代码。这些地址是以4字节为间隔的,
所以仅仅能够容纳得下一条指令,那就是跳转指令。上面的代码都是一条条的跳转指令,位于处理器规
定的相应地址上。因此处理器探测到中断时就有法可依,否则跳转到某个不可预知的地址,就有可能跑
飞。ldr pc,*就是将特定的地址装载到PC指针寄存器中,其实就是跳转的意思。 */
#ifdef CONFIG_SPL_BUILD
_undefined_instruction: .word _undefined_instruction _software_interrupt: .word _software_interrupt _prefetch_abort: .word _prefetch_abort _data_abort: .word _data_abort _not_used: .word _not_used _irq: .word _irq _fiq: .word _fiq _pad: .word 0x12345678 /* now 16*4=64 */ #else
_undefined_instruction: .word undefined_instruction _software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort _data_abort: .word data_abort _not_used: .word not_used _irq: .word irq _fiq: .word fiq _pad: .word 0x12345678 /* now 16*4=64 */ #endif /* CONFIG_SPL_BUILD */ /*
这里首先还是一个宏开关,应该在某处有一个宏定义,可以打开下面的代码。不过设置中断向量是必须的,
所以我们假定这个宏开关打开。还是看那个前辈的文章,我们学习到: “
.word Define word expr (32bit numbers) .word expr {, …} .word 144511, 0x11223 _undefined_instruction是一个标号,此处分配了一个word=32bit=4字节的地址空间,里面存放的值是
undefined_instruction。而此处_undefined_instruction也就是该地址空间的地址了。在后面的代码,我
们可以看到,undefined_instruction也是一个标号,即一个地址值,对应着就是在发生“未定义指令”的
时候,系统所要去执行的代码。”
其实他说得已经很清楚了,就是前面的ldr pc, _undefined_instruction会跳转到后面 undefined_instruction标号处执行,中间只不过加了一级存储空间的分配。至于为什么这样分配,有待以
后研究。这里AM335x的代码有个_pad: .word 0x12345678 /* now 16*4=64 */,这应该是德州仪器针对
特定问题所做的修改,可能也是为了实现某种跳转,但肯定不是中断向量的一部分,因为在硬件上没有相应 的中断地址。
通过上面的叙述,就知道了宏开关else部分的作用了,而上面的宏开关,不知是否是二级bootloader
(Second Program Loader)的意思,不过看情况是发生原地跳转死循环,总之先了解到这个层次。 */
.global _end_vect _end_vect: .balignl 16,0xdeadbeef
相关推荐: