本来不想写的,想想还是轻描淡写吧:好理解的一笔带过,难理解的重点介绍。
.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,在ubootoarddaveB2config.mk中赋值
_armboot_start:全局变量,指示uboot起始地址,初始化为_start,与_bss_start共同构成uboot的大小(sizeof(uboot)=_bss_start-_armboot_start)
_bss_start:BSS:Block Started by Symbol segment,全局变量,定义在ubootoarddaveB2u-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在ubootoarddaveB2lowlevel_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个[page]
@如果源地址和目标地址不一样,则说明没搬运完
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:定义在 ubootincludeconfigB2.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
返回调用处
上一篇:STM32学习手记③-EXTI中断
下一篇:自制bootloader 之 文本代码
推荐阅读最新更新时间:2024-03-16 14:26