专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

uboot之\cpu\s3c44b0\start.S文件的详解

作者:huorr520   来源:本站原创   点击数:  更新时间:2010年12月25日   【字体:

今天总算看完了,理解完了,理解清楚了,看透了start.S~~~~~~

本来不想写的,想想还是轻描淡写吧:好理解的一笔带过,难理解的重点介绍。

.globl _start
_start: b       reset
 add pc, pc, #0x0c000000
 add pc, pc, #0x0c000000
 add pc, pc, #0x0c000000
 add pc, pc, #0x0c000000
 add pc, pc, #0x0c000000
 add pc, pc, #0x0c000000
 add pc, pc, #0x0c000000

 .balignl 16,0xdeadbeef

_start 全局变量,uboot代码入口,在uboot中偏移地址_start_offset=0。除了reset中断外,其他中断都跳到SDRAM中去执行中断,因此,用add指令,增加跳转范围。用LDR也是可以的,不过得另外定义一些变量,不如add省事,呵呵~~至于.balignl 16,0xdeadbeef网上都是说将地址对齐为16的倍数。为什么要对齐呢??不知道

*************************************************************************************************

_TEXT_BASE:
 .word TEXT_BASE

.globl _armboot_start
_armboot_start:
 .word _start
.globl _bss_start
_bss_start:
 .word __bss_start

.globl _bss_end
_bss_end:
 .word _end

全局变量定义声明:

_TEXT_BASE:全局变量指示uboot将被放在SDRAM中的地址,初始化为TEXT_BASE,在uboot\board\dave\B2\config.mk中赋值

_armboot_start:全局变量,指示uboot起始地址,初始化为_start,与_bss_start共同构成uboot的大小(sizeof(uboot)=_bss_start-_armboot_start)

_bss_start:BSS:Block Started by Symbol segment,全局变量,定义在uboot\board\dave\B2\u-boot.lds。用来存放未初始化的全局变量的一块内存。_bss_start:BSS段起始地址

_bss_start:BSS段结束地址,_bss_start-_bss_end=sizeof(BSS)

*************************************************************************************************

#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
 .word 0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
 .word 0x0badc0de
#endif

如果要用到IRQ和FIQ就设置相应堆栈

*************************************************************************************************

先到这~~吃饭去了

接着写吧,有点难继续下:

reset:
 mrs r0,cpsr
 bic r0,r0,#0x1f
 orr r0,r0,#0x13
 msr cpsr,r0

@系统上电复位后设置成SVC模式

@寄存器操作方法:读----修改-----回写

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
 bl cpu_init_crit
 bl lowlevel_init
#endif

@如果没有定义CONFIG_SKIP_LOWLEVEL_INIT(顾名思义:跳过底层初始化)

@没有定义的话那就跳进去进行初始化吧。

@cpu_init_crit函数在本文本中 后面介绍

@lowlevel_init在\uboot\board\dave\B2\lowlevel_init.S 完成存储器初始化(<1.4的uboot不是这个名称,好像是memap.S??大概是这个名字)

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:    /* relocate U-Boot to RAM     */
 adr r0, _start  /* r0 <- current position of code   */
 ldr r1, _TEXT_BASE  /* test if we run from flash or RAM */
 cmp     r0, r1                  /* don't reloc during debug         */
 beq     stack_setup

@如果没有定义CONFIG_SKIP_RELOCATE_UBOOT(顾名思义:跳过重定位)

@那就要进行重定位判断了

@先判断uboot放置的地址,是在flash还是在SDRAM中。如果在flash中,则要重定位,即把uboot代码整个搬@移至SDRAM中TEXT_BASE地址处;如果在SDRAM中,则不需要搬移,直接跳到堆栈设置。

@关于怎么判断的,详见日志:uboot relocate

 ldr r2, _armboot_start
 ldr r3, _bss_start
 sub r2, r3, r2  /* r2 <- size of armboot            */
 add r2, r0, r2  /* r2 <- source end address         */

@如果要搬移的话,计算uboot的大小

@并将整个搬移后的地址放入r2,以进行判断是否搬运完了

copy_loop:
 ldmia r0!, {r3-r10}  /* copy from source address [r0]    */
 stmia r1!, {r3-r10}  /* copy to   target address [r1]    */
 cmp r0, r2   /* until source end addreee [r2]    */
 ble copy_loop

@代码搬移,每次搬运r3-r10个

@如果源地址和目标地址不一样,则说明没搬运完

adr r0, real_vectors
 add r2, r0, #1024
 ldr r1, =0x0c000000
 add r1, r1, #0x08
vector_copy_loop:
 ldmia r0!, {r3-r10}
 stmia r1!, {r3-r10}
 cmp r0, r2
 ble vector_copy_loop

@将flash地址中的中断向量表搬移到SDRAM中,构成二级中断向量表

@当有中断到来时,先跳转到flash地址的中断向量表(0x00000000),再在程序开始处的跳转指令跳转到

@SDRAM中的中断向量表(0x0c000000)
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */

@结束重定位,进行堆栈设置

stack_setup:
 ldr r0, _TEXT_BASE  /* upper 128 KiB: relocated uboot   */
 sub r0, r0, #CFG_MALLOC_LEN /* malloc area                      */
 sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo           

@按照uboot存储器映射图,uboot被映射到SDRAM的高端。而在SDRAM地址减生长方向依次为

@CFG_MALLOC_LEN,CFG_GBL_DATA_SIZE,IRQ&FIQ(if define) abort_stack(12B)

@CFG_ENV_SIZE:环境变量存储空间,紧接着MALLOC_LEN的前面(1024)

@MALLOC_LEN:定义在\ uboot\include\config\B2.h 为malloc()函数预留的数据空间

@同时包含CFG_ENV_SIZE,大小为(CFG_ENV_SIZE + 128*1024)

@GBL_DATA_SIZE:全局信息表gd的数据空间(128)

@IRQ&FIQ:如果定义了的话就分配
#ifdef CONFIG_USE_IRQ
 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif

@如果定义了CONFIG_USE_IRQ 则分配IRQ和FIQ堆栈
 sub sp, r0, #12  /* leave 3 words for abort-stack    */

@分配12个字节空间为用户栈

@注:CFG_MALLOC_LEN + CFG_GBL_DATA_SIZE + CONFIG_USE_IRQ + 12 =

@TEXT_BASE - SDRAM_start

 ldr pc, _start_armboot

_start_armboot: .word start_armboot

@跳转到_start_armboot

@_start_armboot用start_armboot初始化,即第一个C函数

*************************************************************************************************

#define INTCON (0x01c00000+0x200000)
#define INTMSK (0x01c00000+0x20000c)
#define LOCKTIME (0x01c00000+0x18000c)
#define PLLCON (0x01c00000+0x180000)
#define CLKCON (0x01c00000+0x180004)
#define WTCON (0x01c00000+0x130000)

@cpu初始化相关的一些寄存器名宏定义

*************************************************************************************************
cpu_init_crit:
 /* disable watch dog */
 ldr  r0, =WTCON
 ldr r1, =0x0
 str r1, [r0]

@关闭看门狗

*************************************************************************************************
 ldr r1,=INTMSK
 ldr r0, =0x03fffeff
 str r0, [r1]

 ldr r1, =INTCON
 ldr r0, =0x05
 str r0, [r1]

@屏闭所有中断,只开启timer5做linux时钟

*************************************************************************************************
 ldr r1, =LOCKTIME
 ldrb r0, =800
 strb r0, [r1]

@设置时钟锁定延迟时间

 #if CONFIG_S3C44B0_CLOCK_SPEED==66
 ldr r0, =0x34031  /* 66MHz (Quartz=11MHz) */
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
 ldr r0, =0x610c1 /*B2: Xtal=20mhz Fclk=75MHz  */
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif

@如果定义了一些系统时钟的相关宏定义则设置相应的PLLCON

@当然自己也可以定义自己想要的时钟 只需设置相应的值即可

str r0, [r1]

ldr r1,=CLKCON
 ldr r0, =0x7ff8
 str r0, [r1]

@使能所有模块的时钟

 mov pc, lr

返回调用处
 

关闭窗口

相关文章