分类: 嵌入式
2011-05-19 21:32:39
/* armboot - Startup Code for XScale */
.globl _start
_start: b reset /*跳转到reset标号执行*/
reset:
mrs r0,cpsr /* 读cpsr寄存器状态 */
bic r0,r0,#0x1f /* 位清除,清除0x1f对应的位 */
orr r0,r0,#0x13 /* 设置M=10011,superviser 模式 */
msr cpsr,r0 /* 写cpsr寄存器 */
bl cpu_init_crit /* 跳转到cpu_init_crit执行系统的关键初始化 */
cpu_init_crit:
/* mask all IRQs */
ldr r0, IC_BASE /* r0 <- Interrupt-Controller base address */
mov r1, #0x00
str r1, [r0, #ICMR_OFFSET] /* ICMR寄存器清零,屏蔽所有的中断 */
/*
* 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.
*/
bl lowlevel_init /* 跳转到lowlevel_init执行SDRAM相关的初始化,参见对lowlevel_init.S的分析 */
#if defined(CFG_CPUSPEED)
/*
* 系统频率的计算方法如下:
* Turbo-mode frequency (T) = 13-MHz processor-oscillator frequency * L * N
* Run-mode frequency (R) = 13-MHz processor-oscillator frequency * L
* System-bus frequency = 13-MHz processor-oscillator frequency * L / B,
* where B = 1 (when in fast-bus mode) or B = 2 (when not in fast-bus mode)
* For CCCR[A] = 0 :
* Memory-controller frequency = 13-MHz processor-oscillator frequency * L / M,
* where M = 1 (L = 2-10), M = 2 (L = 11-20), or M = 4 (L = 21-31)
* LCD frequency = 13-MHz processor-oscillator frequency * L / K,
* where K = 1 (L = 2-7), K = 2 (L = 8-16), or K = 4 (L = 17-31)
* For CLKCFG[B] = 0 and CCCR[A] = 1 :
* Memory-controller frequency = 13-MHz processor-oscillator frequency * L / 2
* LCD frequency = 13-MHz processor-oscillator frequency * L / K,
* where K = 1 (L = 2-7), K = 2 (L = 8-16), or K = 4 (L = 17-31)
* For CLKCFG[B] = 1 and CCCR[A] = 1 :
* Memory-controller frequency = 13-MHz processor-oscillator frequency * L
* LCD frequency = 13-MHz processor-oscillator frequency * L / K,
* where K = 1 (L = 2-7), K = 2 (L = 8-16), or K = 4 (L = 17-31)
*/
/* set clock speed */
ldr r0, =CC_BASE
ldr r1, cpuspeed
str r1, [r0, #CCCR_OFFSET] /* Core Clock Configuration Register */
ldr r1, [r0, #CCCR_OFFSET] /* read back to make sure write action completed */
mov ip, lr /* 临时寄存器 <- 链接寄存器*/
bl xlli_freq_change /* 跳到标号xlli_freq_change执行 */
mov lr, ip
/* Before enabling fast bus mode, must make sure Memory Controller is configured properly */
#if defined(CONFIG_SYSBUS_208)
mov r0, #0x0B /* Fast bus | Freq. Change | Turbo mode */
#else
mov r0, #0x03 /* ~Fast bus | Freq. Change | Turbo mode */
#endif
mcr p14, 0, r0, c6, c0, 0 /* Write CCLKCFG */
#if defined(CONFIG_MEMC_BS) /* memory controller buffer strength control */
ldr r0, =MEMC_BASE
ldr r1, =CFG_BSCNTR0_VAL
str r1, [r0, #BSCNTR0_OFFSET]
ldr r1, =CFG_BSCNTR1_VAL
str r1, [r0, #BSCNTR1_OFFSET]
ldr r1, =CFG_BSCNTR2_VAL
str r1, [r0, #BSCNTR2_OFFSET]
ldr r1, =CFG_BSCNTR3_VAL
str r1, [r0, #BSCNTR3_OFFSET]
ldr r1, [r0, #BSCNTR3_OFFSET] /* Make sure value is written */
#endif
setspeed_done:
#endif
.global normal_boot
normal_boot:
/* Memory interfaces are working. Disable MMU and enable I-cache. */
ldr r0, =0x2001 /* enable access to all coproc. */
mcr p15, 0, r0, c15, c1, 0 /* enable access to CP13 CP0*/
CPWAIT /* wait for effect */
mcr p15, 0, r0, c7, c10, 4 /* drain the write & fill buffers */
CPWAIT
mcr p15, 0, r0, c7, c7, 0 /* flush Icache, Dcache and BTB */
CPWAIT
mcr p15, 0, r0, c8, c7, 0 /* flush instuction and data TLBs */
CPWAIT
/* Enable the Icache */
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #0x1800 /* Instruction Cache Enable, Branch Target Buffer Enable */
mcr p15, 0, r0, c1, c0, 0
CPWAIT
@ mov pc, lr
b cpu_init_done /* call return back */
/* Frequency Change Sequence from BLOB */
xlli_freq_change:
mrc p14, 0, r0, c6, c0, 0 /* Get present status (preserve Turbo and Fast Bus bits) */
orr r0, r0, #2 /* Set the F bit, Frequency Change, A change sequence is initiated when F is set. */
mcr p14, 0, r0, c6, c0, 0 /* initiate the frequency change sequence */
/*
* If the clock frequency is chaged, the MDREFR Register must be rewritten, even
* if it's the same value. This will result in a refresh being performed and the
* refresh counter being reset to the reset interval. (Section 13.10.3, pg 13-17 of EAS)
*/
ldr r4, =MEMC_BASE /* Get memory controller base address */
ldr r1, [r4, #MDREFR_OFFSET] /* Get the current state of MDREFR */
str r1, [r4, #MDREFR_OFFSET] /* Re-write this value */
mov pc, lr /* return to calling routine */
/* RS: ??? */
.macro CPWAIT /* Canonical method to wait for CP15 update */
mrc p15,0,r0,c2,c0,0 /* arbitrary read of CP15 */
mov r0,r0 /* nop, wait for it */
sub pc,pc,#4 /* branch to next instruction */
/* At this point, any previous CP15 writes are guaranteed to have taken effect. */
.endm
cpu_init_done:
#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
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
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 /* CONFIG_SKIP_RELOCATE_UBOOT */
/* Set up the stack */
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 —— 栈指针寄存器 */
clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */
clbss_l:str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
ble clbss_l
ldr pc, _start_armboot /* 跳转到start_armboot执行, 参见对lib_arm/board.c的分析 */
_start_armboot: .word start_armboot
***************************************************************************************************************
U-Boot源代码阅读笔记(二) —— 对lowlevel_init.S的分析本文主要分析与U-Boot启动过程相关的汇编代码lowlevel_init.S,目标平台以PXA270为例。
文件位于board/myboard/lowlevel_init.S,主要执行内存相关的初始化
- 把链接寄存器LR(即R14)的值转存到寄存器R10中,以便lowlevel_init完成后恢复执行
.globl lowlevel_init
lowlevel_init:
mov r10, lr
- 按顺序初始化GPIO寄存器: GPSR GPCR GRER GFER GPDR GAFR PSSR
/* Set up GPIO pins first */
ldr r0, =GPSR0
ldr r1, =CFG_GPSR0_VAL
str r1, [r0]
.....
- 初始化内存控制器
/* Initlialize Memory Controller */
@ skip memory init if we're run in ram(must be a JTAG run)
mov r0, pc
ldr r1, =0xa0000000
and r0, r0, r1 /* 把当前PC寄存器的值与0xa0000000逻辑与*/
cmp r0, r1 /* 如果结果等于0xa0000000,说明uboot是从RAM启动的 */
beq mem_init_done /* 那么就需要跳过RAM初始化, 直接跳转到mem_init_done执行 */
/* 具体的初始化操作与目标板有很大相关性,下面以我的PXA270开发板为例 */
mem_init:
@ get memory controller base address
ldr r1, =MEMC_BASE /* 内存控制器基地址 */
- 初始化内存控制器 Step 1
@****************************************************************************
@ Step 1
@
@ Step 1a
/* Initlialize Static Memory Control register */
/* 初始化MSCx寄存器需要设置 */
/* RBUFFx —— Return Data Buffer vs. Streaming Behavior */
/* RRRx —— ROM/SRAM Recovery Time */
/* RDNx —— ROM Delay Next Access */
/* RDFx —— The ROM Delay First Access */
/* RBWx —— ROM Bus Width */
/* RTx —— ROM Type */
@ write msc0, read back to ensure data latches
ldr r2, =CFG_MSC0_VAL
str r2, [r1, #MSC0_OFFSET]
ldr r2, [r1, #MSC0_OFFSET] /* Ensure that the new value has been accepted and programmed */
......
@ Step 1b
/* 配置PCMCIA和CF需要设置下面这些寄存器 */
@ MECR —— Expansion Memory (PC Card/CompactFlash) Bus Configuration register
@ MCMEMx —— PC Card Interface Common Memory Space Socket 0/1 Timing Configuration register
@ MCATTx —— PC Card Interface Attribute Space Socket 0/1 Timing Configuration register
@ MCIOx —— PC Card Interface I/O Space Socket 0/1 Timing Configuration register
@ Step 1c
@ fly-by-dma is defeatured on this part
@ write flycnfg —— Fly-by DMA DVAL<1:0> polarities
@ldr r2, =CFG_FLYCNFG_VAL
@str r2, [r1, #FLYCNFG_OFFSET]
@ Step 1d
@ fetch platform value of mdcnfg —— SDRAM Configuration register
@
ldr r2, =CFG_MDCNFG_VAL
@ disable all sdram banks
@
bic r2, r2, #(MDCNFG_DE0 | MDCNFG_DE1)
bic r2, r2, #(MDCNFG_DE2 | MDCNFG_DE3)
str r2, [r1, #MDCNFG_OFFSET]
@ Step 1e
@ write MDREFR —— SDRAM Refresh Control register
ldr r3, = CFG_MDREFR_VAL
ldr r2, = 0xFFF /* DRI mask */
and r3, r3, r2
ldr r4, [r1, #MDREFR_OFFSET] /* reset value */
bic r4, r4, r2 /* clear DRI field —— SDRAM Refresh Interval for All Partitions */
orr r4, r4, r3
orr r4, r4, #MDREFR_K0RUN /* SDCLK0 Run Control/Status */
bic r4, r4, #MDREFR_K0DB2 /* SDCLK0 Divide by 2 Control/Status */
bic r4, r4, #MDREFR_K0DB4 /* SDCLK0 Divide by 4 Control/Status */
bic r4, r4, #MDREFR_K2FREE /* SDCLK<2> Free-Running Control */
bic r4, r4, #MDREFR_K1FREE
bic r4, r4, #MDREFR_K0FREE
orr r4, r4, #MDREFR_SLFRSH /* SDRAM Self-Refresh Control/Status, Self-refresh enabled */
/* write back MDREFR */
str r4, [r1, #MDREFR_OFFSET]
- 初始化内存控制器 Step 2
@ Step 2
@ Configure synchronus flash memory
- 初始化内存控制器 Step 3
@ Step 3
@ Configure SDRAM
ldr r2, =CFG_MDREFR_VAL
bic r2, #MDREFR_APD /* SDRAM/Synchronous Static Memory Auto-Power-Down Enable */
str r2, [r1, #MDREFR_OFFSET]
ldr r3, [r1, #MDREFR_OFFSET] @ read back to make sure write action completed
- 初始化内存控制器 Step 4
@ Step 4
@ write initial value of mdcnfg, w/o enabling sdram banks
@
ldr r2, =CFG_MDCNFG_VAL
bic r2, r2, #(MDCNFG_DE0 | MDCNFG_DE1)
bic r2, r2, #(MDCNFG_DE2 | MDCNFG_DE3)
str r2, [r1, #MDCNFG_OFFSET]
@ldr r2, = CFG_MDREFR_VAL
@str r2, [r1, #MDREFR_OFFSET]
- 初始化内存控制器 Step 5
@ Step 5
@ pause for 200 uSecs
@
ldr r3, =OSCR @ reset the OS Timer Count to zero
mov r2, #0
str r2, [r3]
ldr r4, =0x300 @ really 0x2E1 is about 200usec, so 0x300 should be plenty ——3.25MHz clock
1:
ldr r2, [r3] /* r2读OS Timer Count*/
cmp r4, r2 /* 比较OS Timer Count和r4 */
bgt 1b /* 如果时间没到就循环 */
- 初始化内存控制器 Step 6
@ Step 6
@ Disable XScale Data Cache
mov r0, #0x78 @turn everything off
mcr p15, 0, r0, c1, c0, 0 @(caches off, MMU off, etc.) /* 设置协处理器P15 */
- 初始化内存控制器 Step 7 - 11
@ Step 7
@ Access memory *not yet enabled* for CBR refresh cycles (8) *NOTE: hardware reset only
@ - CBR is generated for all banks
ldr r2, =CFG_DRAM_BASE
str r2, [r2]
str r2, [r2]
str r2, [r2]
str r2, [r2]
str r2, [r2]
str r2, [r2]
str r2, [r2]
str r2, [r2]
@ Step 8
@ Enable data cache
@ Step 9
@ Enable SDRAM
@fetch current mdcnfg value
ldr r3, [r1, #MDCNFG_OFFSET]
orr r3, r3, #MDCNFG_DE0 /* enable sdram bank0 */
@write back mdcnfg, enabling the sdram bank(s)
str r3, [r1, #MDCNFG_OFFSET]
@ Step 10
@ write mdmrs —— SDRAM Mode Register Set Configuration Register
@
ldr r2, =CFG_MDMRS_VAL
str r2, [r1, #MDMRS_OFFSET]
@ Step 11
@ Enable MDREFR[APD] optionally
ldr r2, =CFG_MDREFR_VAL
str r2, [r1, #MDREFR_OFFSET]
- Done Memory Init
mem_init_done:
@********************************************************************
@ Disable (mask) all interrupts at the interrupt controller
@
@ clear the interrupt level register (use IRQ, not FIQ)
@
mov r1, #0
ldr r2, =ICLR
str r1, [r2]
@ Set interrupt mask register
@
ldr r1, =CFG_ICMR_VAL /* set ICMR = 0, no interrupts enabled */
ldr r2, =ICMR
str r1, [r2]
@ ********************************************************************
@ Disable the peripheral clocks, and set the core clock
@
@ Turn Off ALL on-chip peripheral clocks for re-configuration
@
ldr r1, =CKEN /*clock enable register */
mov r2, #0
str r2, [r1]
@ set core clocks
@
ldr r1, =CCCR /* core clock configuration register */
ldr r2, [r1, #0]
ldr r3, =(CCCR_L_MASK | CCCR_2N_MASK)
bic r2, r2, r3
/* Run-Mode-to-Oscillator Ratio (L) creates the nominal run mode frequency by multiplying the 13-MHz processor oscillator by L. */
/* Turbo-Mode-to-Run-Mode Ratio (N) creates the nominal turbo-mode frequency by multiplying the run-mode frequency by N. */
/* core freq: Normal 208MHz, Turbo 312MHz */
ldr r3, =(16 | 3<<7) /* Turbo-Mode-to-Run-Mode Ratio, N = 3/2 */
orr r2, r2, r3 /* Run-Mode-to-Oscillator Ratio = 16*13 MHz, */
str r2, [r1]
#ifdef ENABLE32KHZ
@ enable the 32Khz oscillator for RTC and PowerManager
@
ldr r1, =OSCC /* oscillator configuration register */
mov r2, #OSCC_OON /* 32.768kHz OON (write-once only bit) */
str r2, [r1]
@ NOTE: spin here until OSCC.OOK get set,
@ meaning the PLL has settled.
@
60:
ldr r2, [r1]
ands r2, r2, #1 /* r2 = r2 & 0x1, 取出最低位数据 */
beq 60b
#endif
@ Turn on needed clocks
@
ldr r1, =CKEN
ldr r2, =CFG_CKEN_VAL
str r2, [r1]mov pc, r10 /* 恢复链接寄存器的值到PC,返回start.S调用lowlevel_init处继续执行 */
- lowlevel_init完成
@ End lowlevel_init