您的位置:首页 > 其它

s3c2410 u-boot源码分析start.S

2009-09-23 18:56 471 查看
根据board/samsumg/smdk2410下的u-boot.lds这个链接脚本知道u-boot启动的第一阶段函数是在cpu/arm920t/start.S。完成的功能主要包括

1:cpu自身的初始化:包括MMU,catch,时钟系统,SDRAM控制系统的初始话。

2:重定位:把自己从flash中搬到SDRAM 中

3:分配堆栈空间,设置堆栈指针

4:清零BSS数据段

5:跳转到第二阶段入口函数。

具体分析如下:

.globl _start

@设置异常向量表,其中_start是GNU 汇编的默认入口标签。注意ldr r0,0x1234是把0X1234中的内容写到R0中,ldr r0,=0x1234,是将1234这个值写到R0中,以及ADR 是用来加载地址。

_start: b start_code

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

@.word为GUN 汇编分配一段字内存单元,下面几句话相当于是C语言中的变量名和变量值。

_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

@全局符号定义

_TEXT_BASE:

.word TEXT_BASE@在board/samsumg/smdk2410中定义为3ff80000..即UBOOT映像文件所在地址

.globl _armboot_start

_armboot_start:

.word _start

@下面主要在u-boot.lds链接脚本中定义

.globl _bss_start

_bss_start:

.word __bss_start

.globl _bss_end

_bss_end:

.word _end

@下面主要为start_code 的实现

start_code:

@设置当前状态为SVC32模式

mrs r0,cpsr

bic r0,r0,#0x1f @相应位置清零

orr r0,r0,#0xd3 @相应位置1,同时关闭IRQ,FIQ。

msr cpsr,r0

@关闭看门狗,关中断,设置时钟分频控制寄存器。pWTCON是看门狗控制寄存器,INTMSK是中断屏蔽寄存器,INTSUBMSK是中断子屏蔽寄存器,CLKDIVN是clock divisor register,用来设置FCLK,HCLK,PCLK三者的比例。

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)

/* turn off the watchdog */

# if defined(CONFIG_S3C2400)

# define pWTCON 0x15300000

# define INTMSK 0x14400008 /* Interupt-Controller base addresses */

# define CLKDIVN 0x14800014 /* clock divisor register */

#else

# define pWTCON 0x53000000

# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */

# define INTSUBMSK 0x4A00001C

# define CLKDIVN 0x4C000014 /* clock divisor register */

# endif

@关看门狗

ldr r0, =pWTCON

mov r1, #0x0

str r1, [r0]

@关闭主中断屏蔽寄存器

mov r1, #0xffffffff

ldr r0, =INTMSK

str r1, [r0]

# if defined(CONFIG_S3C2410)

@关闭副中断屏蔽寄存器

ldr r1, =0x3ff

ldr r0, =INTSUBMSK

str r1, [r0]

# endif

@设置时钟分频控制寄存器。

/* FCLK:HCLK:PCLK = 1:2:4 *
/FCLK为核心提供时钟,HCLK为AHB(ARM920T,内存控制器,中断控制器,LCD控制器,DMA和主USB模块)提供时
钟,PCLK为APB(看门狗、IIS、I2C、PWM、MMC、ADC、UART、GPIO、RTC、SPI)提供时钟

/* default FCLK is 120 MHz ! */

ldr r0, =CLKDIVN

mov r1, #3

str r1, [r0]

#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */

@执行CPU初始话。

176 #ifndef CONFIG_SKIP_LOWLEVEL_INIT

178 bl cpu_init_crit @如果没有定义CONFIG_SKIP_LOELEVEL_INIT,则执行cpu_init_crit.见236-268下


179 #endif

@重新定位u-boot到SDRAM中

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

181 relocate: /* relocate U-Boot to RAM */

182 adr r0, _start @通过adr指令得到当前代码的地址信息:如果U-boot是从RAM开始运行,则从adr,r0,_start得到的地址信息为r0=_start=_TEXT_BASE=TEXT_BASE=0x3ff80000;如果U-boot从Flash开始运行,即从处理器对应的地址运行,则r0=0x0000,这时将会执行copy_loop标识的那段代码了

183 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */

184 cmp r0, r1 /* don't reloc during debug */

185 beq stack_setup @
如果r0等于r1,跳过重定位代码



186

187 ldr r2, _armboot_start@_start的内容写入r2

188 ldr r3, _bss_start @_bss_start的内容写入r3

189 sub r2, r3, r2 @计算armboot所占字节大小

190 add r2, r0, r2 @armboot结束地址

191 @实现从flash中拷贝到_TEXT_BASE(0x3ff80000)所在的地址中去


192 copy_loop:

193 ldmia r0!, {r3-r10} /* copy from source address [r0] */

194 stmia r1!, {r3-r10} /* copy to target address [r1] */

195 cmp r0, r2 /* until source end addreee [r2] */

196 ble copy_loop

197 #endif /* CONFIG_SKIP_RELOCATE_UBOOT */

198

199 @初始化堆栈
*/

200 stack_setup:

201 ldr r0, _TEXT_BASE @3ff80000

202 sub r0, r0, #CONFIG_SYS_MALLOC_LEN @ 向下内存分配,为malloc预留分配空间

203 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE@
全局数据结构空间


204 #ifdef CONFIG_USE_IRQ

205 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)@ 为IRQ,FIQ分配空间

206 #endif

207 sub sp, r0, #12 @为abort异常预留12字节的空间,并将当前的地址赋给sp,这样就为内存栈设置好了,之后如果在u-boot中运行程序时需要使用栈的时候就从这里开始。

208 @清空数据段

209 clear_bss:

210 ldr r0, _bss_start /* find start of bss segment */

211 ldr r1, _bss_end /* stop here */

212 mov r2, #0x00000000 /* clear */

213

214 clbss_l:str r2, [r0] /* clear loop... */

215 add r0, r0, #4

216 cmp r0, r1

217 ble clbss_l

219 ldr pc, _start_armboot@跳转到_start_armboot,也就是函数 start_armboot,此函数存放在u-boot-2009.03/lib_arm/board.c,这样就到了u-boot的第二阶段了。

220

221 _start_armboot: .word start_armboot



@执行cpu_init_crit.

236 #ifndef CONFIG_SKIP_LOWLEVEL_INIT

237 cpu_init_crit:

238 /*

239 * flush v4 I/D caches

240 */

241 mov r0, #0

242 mcr p15, 0, r0, c7, c7, 0 @使Icaches和Dcaches无效

243 mcr p15, 0, r0, c8, c7, 0 @使TLB失效

244

245 关闭mmu和cache,这里249行,将13,9,8bit清零(13—异常向量表基地址:0x0, 9—Disable
System Protection, 8—Disable ROM Protection),250行,将7,2,1,0bit清零(7—为0
的时候表示小端字节序,2-- Data Cache Disabled,1-- Alignment Fault checking
disabled,0—为0的话MMU disabled),251行,将bit 1 设置为1表示Fault checking
enabled,252行,将bit 12设置为1表示使能 I-Cache。

@MRC指令的格式为:

@MRC{条件} 协处理器编码,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,协处理器操作码2。

@MRC指令用于将协处理器寄存器中的数据传送到ARM处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令异常。其中协处理器操作码1和协处理器操作码2为协处理器将要执行的操作,目的寄存器为ARM处理器的寄存器,源寄存器1和源寄存器2均为协处理器的寄存器。 指令示例: MRC P3,3,R0,C4,C5,6 ;该指令将协处理器P3的寄存器中的数据传送到ARM处理器寄存器中。

248 mrc p15, 0, r0, c1, c0, 0

249 bic
r0, r0, #0x00002300 @ clear
bits 13, 9:8 (--V- --RS)

250 bic
r0, r0, #0x00000087 @ clear
bits 7, 2:0 (B--- -CAM)

251 orr
r0, r0, #0x00000002 @ set bit
2 (A) Align

252 orr
r0, r0, #0x00001000 @ set bit
12 (I) I-Cache

253 mcr p15, 0, r0, c1, c0, 0

254

260 mov ip, lr @保存当前链接寄存器中的值

261

262 bl lowlevel_init @ @u-boot-2009.03/board/samsung/smdk2410/lowlevel_init.S ,主要是初始话存储控制器件,共13个。只需要设置BWSCON和BANKCONx(x为0-5),而BANK6,BANK7接SDRAM,除了设置
BWSCON和BANKCONx(x为6,7),还需要设置其他四个寄存器,而这13个寄存器的地址是连续的,BWSCON是第一个寄存器

263

264 mov lr, ip

265 mov pc, lr @返回执行relocate。

266 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */

@以下就是各种中断的处理。

@.macro伪操作符标识宏定义的开始,.endm标识宏定义的结束。二者包含的一段代码,称为宏定义体,这样在程序中就可通过宏指令多次调用该代码段。格式:

.macro macroname {parameter{,parameter}...}

...

.endm

宏的参数可直接使用斜线“/字符”来引用,如下“/reg”所示。

@略过

这里重声一下ldr和b的区别:

b跳转指令是个相对跳转指令直接向PC寄存器赋值,依赖当前PC的值,这使得B指令不依赖代码存储的位置,被称为位置无关码

ldr是从内存中的某个位置读出数据,并给PC赋值这个位置的地址是当前PC寄存器的值加上偏移值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: