开篇:
u-boot 第一阶段干了啥事:
1.set the cpu to SVC32 mode 设为管理模式
2.turn off the watchdog 关看门狗
3.mask all IRQs by setting all bits in the INTMR - default 屏蔽所有中断
4.Init 各种设置
4-1.flush v4 I/D caches 清除caches
4-2.disable MMU stuff and caches 禁止mmu和cache
4-3.setup RAM timing 初始化内存
5.Set up the stack设置棧
6.init the clock 初始化时钟
7.relocate 重定位
8.clean bss 清除bss段
9.跳到start_armboot中去,运行第二阶段代码
u-boot第一阶段代码分析:
#include
#include
start.S:
.globl _start
_start: b reset
reset:
/* 1.set the cpu to SVC32 mode */
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
/* 2.turn off the watchdog */
#if defined(CONFIG_S3C2400)
# define pWTCON 0x15300000
# define INTMSK 0x14400008 /* Interupt-Controller base addresses */
# define CLKDIVN 0x14800014 /* clock divisor register */
#elif defined(CONFIG_S3C2410) //这里定义了CONFIG_S3C2410
# define pWTCON 0x53000000
# define INTMOD 0X4A000004
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
# define INTSUBMSK 0x4A00001C
# define CLKDIVN 0x4C000014 /* clock divisor register */
#endif
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) /*向寄存器中写入0,关看们狗*/
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0]
/*3.mask all IRQs by setting all bits in the INTMR - default*/
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
/*4.Init */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT //没有定义CONFIG_SKIP_LOWLEVEL_INIT
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM _TEXT_BASE is running address*/
cmp r0, r1 /* don't reloc during debug */
blne cpu_init_crit
#endif
#ifndef CONFIG_SKIP_LOWLEVEL_INIT //没有定义CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
/* 4-1.flush v4 I/D caches*/
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
/*4-2.disable MMU stuff and caches*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
mcr p15, 0, r0, c1, c0, 0
/*4-3.setup RAM timing*/
/ * before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
* find a lowlevel_init.S in your board directory.*/
mov ip, lr //保存子程序的返回地址
bl lowlevel_init
mov lr, ip
mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
说明:下面初始化内存控制器的时序是跟单板相关的,将其放在board\100ask24x0\lowlevel_init.S
lowlevel_init.S:
_TEXT_BASE:
.word TEXT_BASE
.globl lowlevel_init
lowlevel_init:
/* memory control configuration */
/* make r0 relative the current location so that it r0=>存储相对于运行地址的位移 这时内存还未初始化,不能直接读地址*/
/* reads SMRDATA out of FLASH rather than memory ! 从flash中读出数据而不是从内存中*/
ldr r0, =SMRDATA
ldr r1, _TEXT_BASE
sub r0, r0, r1
ldr r1, =BWSCON /* Bus Width Status Controller */
add r2, r0, #13*4
0:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne 0b
/* everything is fine now */
mov pc, lr //返回
.ltorg
/* the literal pools origin */
SMRDATA:
.word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
.word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
.word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
.word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
.word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
.word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
.word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
.word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
.word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
.word 0xb1
.word 0x30
.word 0x30
说明:初始化之后回到start.s中
start.s
/* 5.Set up the stack 下面要运行c程序了 */
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 */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack */
设置完棧之后sp的情况:
/*6.init the clock*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl clock_init
#endif
说明:时钟是和单板相关的,这里在board\100ask24x0\boot_init.c中初始化
static inline void delay (unsigned long loops)
{
__asm__ volatile ("1:\n"
"subs %0, %1, #1\n"
"bne 1b":"=r" (loops):"0" (loops));
}
/* S3C2440: Mpll = (2*m * Fin) / (p * 2^s), UPLL = (m * Fin) / (p * 2^s)
* m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2
*/
#define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))
#define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
#define S3C2440_MPLL_100MHZ ((0x5c<<12)|(0x01<<4)|(0x03))
#define S3C2440_UPLL_96MHZ ((0x38<<12)|(0x02<<4)|(0x01))
#define S3C2440_UPLL_48MHZ ((0x38<<12)|(0x02<<4)|(0x02))
#define S3C2440_CLKDIV (0x05) // | (1<<3)) /* FCLK:HCLK:PCLK = 1:4:8, UCLK = UPLL/2 */
#define S3C2440_CLKDIV188 0x04 /* FCLK:HCLK:PCLK = 1:8:8 */
#define S3C2440_CAMDIVN188 ((0<<8)|(1<<9)) /* FCLK:HCLK:PCLK = 1:8:8 */
/* Fin = 16.9344MHz */
#define S3C2440_MPLL_399MHz_Fin16MHz ((0x6e<<12)|(0x03<<4)|(0x01))
#define S3C2440_UPLL_48MHZ_Fin16MHz ((60<<12)|(4<<4)|(2))
/* S3C2410: Mpll,Upll = (m * Fin) / (p * 2^s)
* m = M (the value for divider M)+ 8, p = P (the value for divider P) + 2
*/
#define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))
#define S3C2410_UPLL_48MHZ ((0x28<<12)|(0x01<<4)|(0x02))
#define S3C2410_CLKDIV 0x03 /* FCLK:HCLK:PCLK = 1:2:4 */
void clock_init(void)
{
S3C24X0_CLOCK_POWER *clk_power = (S3C24X0_CLOCK_POWER *)0x4C000000;
/* support both of S3C2410 and S3C2440, by www.100ask.net */
if (isS3C2410)
{
/* FCLK:HCLK:PCLK = 1:2:4 */
clk_power->CLKDIVN = S3C2410_CLKDIV;
/* change to asynchronous bus mod */
__asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register */
"orr r1, r1, #0xc0000000\n" /* Asynchronous */
"mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register */
:::"r1"
);
/* to reduce PLL lock time, adjust the LOCKTIME register */
clk_power->LOCKTIME = 0xFFFFFFFF;
/* configure UPLL for usb*/
clk_power->UPLLCON = S3C2410_UPLL_48MHZ;
/* some delay between MPLL and UPLL */
delay (4000);
/* configure MPLL */
clk_power->MPLLCON = S3C2410_MPLL_200MHZ;
/* some delay between MPLL and UPLL */
delay (8000);
}
else
{
/* FCLK:HCLK:PCLK = 1:4:8 */
clk_power->CLKDIVN = S3C2440_CLKDIV;
/* change to asynchronous bus mod */
__asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register */
"orr r1, r1, #0xc0000000\n" /* Asynchronous */
"mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register */
:::"r1"
);
/* to reduce PLL lock time, adjust the LOCKTIME register */
clk_power->LOCKTIME = 0xFFFFFFFF;
/* configure UPLL for usb */
clk_power->UPLLCON = S3C2440_UPLL_48MHZ;
/* some delay between MPLL and UPLL */
delay (4000);
/* configure MPLL */
clk_power->MPLLCON = S3C2440_MPLL_400MHZ;
/* some delay between MPLL and UPLL */
delay (8000);
}
}
/*7.relocate*/
#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 clear_bss
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
#if 1
bl CopyCode2Ram /* r0: source, r1: dest, r2: size * 将nand或nor中的代码放入内存中/
说明:具体的nand初始化,以及读取nand和nor这里就不列出了 board\100ask24x0\boot_init.c中
#else
add r2, r0, r2 /* r2 <- source end address */
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
#endif
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
/*8.clean bss*/
clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */
/*9.跳到start_armboot中去,运行第二阶段代码*/
ldr pc, _start_armboot
_start_armboot: .word start_armboot