本文主要分析与U-Boot启动过程相关的汇编代码lowlevel_init.S,目标平台以PXA270为例。 文件位于board/myboard/lowlevel_init.S,主要执行内存相关的初始化 把链接寄存器LR(即R14)的值转存到寄存器R10中,以便lowlevel_init完成后恢复执行 按顺序初始化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 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] lowlevel_init完成 mov pc, r10 /* 恢复链接寄存器的值到PC,返回start.S调用lowlevel_init处继续执行 */
@ End lowlevel_init
|