本文主要分析与U-Boot启动过程相关的汇编代码lowlevel_init.S,目标平台以PXA270为例。<br />文件位于board/myboard/lowlevel_init.S,主要执行内存相关的初始化 把链接寄存器LR(即R14)的值转存到寄存器R10中,以便lowlevel_init完成后恢复执行 按顺序初始化GPIO寄存器: GPSR GPCR GRER GFER GPDR GAFR PSSR /* Set up GPIO pins first */<br /> ldr r0, =GPSR0<br /> ldr r1, =CFG_GPSR0_VAL<br /> str r1, [r0]<br /> .....初始化内存控制器 /* Initlialize Memory Controller */<br /> @ skip memory init if we're run in ram(must be a JTAG run)<br /> mov r0, pc<br /> ldr r1, =0xa0000000<br /> and r0, r0, r1 /* 把当前PC寄存器的值与0xa0000000逻辑与*/<br /> cmp r0, r1 /* 如果结果等于0xa0000000,说明uboot是从RAM启动的 */<br /> beq mem_init_done /* 那么就需要跳过RAM初始化, 直接跳转到mem_init_done执行 */<br /><br />/* 具体的初始化操作与目标板有很大相关性,下面以我的PXA270开发板为例 */<br /><br />mem_init:<br /> @ get memory controller base address<br /> ldr r1, =MEMC_BASE /* 内存控制器基地址 */<br />初始化内存控制器 Step 1 <br />@****************************************************************************<br />@ Step 1<br />@<br /> <br /> @ Step 1a<br /> /* Initlialize Static Memory Control register */<br /> /* 初始化MSCx寄存器需要设置 */<br /> /* RBUFFx —— Return Data Buffer vs. Streaming Behavior */<br /> /* RRRx —— ROM/SRAM Recovery Time */<br /> /* RDNx —— ROM Delay Next Access */<br /> /* RDFx —— The ROM Delay First Access */<br /> /* RBWx —— ROM Bus Width */<br /> /* RTx —— ROM Type */<br /> @ write msc0, read back to ensure data latches<br /> ldr r2, =CFG_MSC0_VAL<br /> str r2, [r1, #MSC0_OFFSET]<br /> ldr r2, [r1, #MSC0_OFFSET] /* Ensure that the new value has been accepted and programmed */<br /> ......<br /><br /> @ Step 1b<br /> /* 配置PCMCIA和CF需要设置下面这些寄存器 */<br /> @ MECR —— Expansion Memory (PC Card/CompactFlash) Bus Configuration register <br /> @ MCMEMx —— PC Card Interface Common Memory Space Socket 0/1 Timing Configuration register<br /> @ MCATTx —— PC Card Interface Attribute Space Socket 0/1 Timing Configuration register<br /> @ MCIOx —— PC Card Interface I/O Space Socket 0/1 Timing Configuration register<br /><br /> @ Step 1c<br /> @ fly-by-dma is defeatured on this part<br /> @ write flycnfg —— Fly-by DMA DVAL<1:0> polarities<br /> @ldr r2, =CFG_FLYCNFG_VAL<br /> @str r2, [r1, #FLYCNFG_OFFSET]<br /><br /> @ Step 1d<br /> @ fetch platform value of mdcnfg —— SDRAM Configuration register<br /> @<br /> ldr r2, =CFG_MDCNFG_VAL<br /><br /> @ disable all sdram banks<br /> @<br /> bic r2, r2, #(MDCNFG_DE0 | MDCNFG_DE1)<br /> bic r2, r2, #(MDCNFG_DE2 | MDCNFG_DE3)<br /> str r2, [r1, #MDCNFG_OFFSET]<br /><br /> @ Step 1e<br /> @ write MDREFR —— SDRAM Refresh Control register<br /> ldr r3, = CFG_MDREFR_VAL<br /> ldr r2, = 0xFFF /* DRI mask */<br /> and r3, r3, r2<br /> ldr r4, [r1, #MDREFR_OFFSET] /* reset value */<br /> bic r4, r4, r2 /* clear DRI field —— SDRAM Refresh Interval for All Partitions */<br /> orr r4, r4, r3<br /> orr r4, r4, #MDREFR_K0RUN /* SDCLK0 Run Control/Status */<br /> bic r4, r4, #MDREFR_K0DB2 /* SDCLK0 Divide by 2 Control/Status */<br /> bic r4, r4, #MDREFR_K0DB4 /* SDCLK0 Divide by 4 Control/Status */<br /> bic r4, r4, #MDREFR_K2FREE /* SDCLK<2> Free-Running Control */<br /> bic r4, r4, #MDREFR_K1FREE<br /> bic r4, r4, #MDREFR_K0FREE<br /> orr r4, r4, #MDREFR_SLFRSH /* SDRAM Self-Refresh Control/Status, Self-refresh enabled */<br /> /* write back MDREFR */<br /> str r4, [r1, #MDREFR_OFFSET]<br />初始化内存控制器 Step 2 初始化内存控制器 Step 3<br /> @ Step 3<br /> @ Configure SDRAM<br /> ldr r2, =CFG_MDREFR_VAL<br /> bic r2, #MDREFR_APD /* SDRAM/Synchronous Static Memory Auto-Power-Down Enable */<br /> str r2, [r1, #MDREFR_OFFSET]<br /> ldr r3, [r1, #MDREFR_OFFSET] @ read back to make sure write action completed<br /><br />初始化内存控制器 Step 4<br /> @ Step 4<br /> @ write initial value of mdcnfg, w/o enabling sdram banks<br /> @<br /> ldr r2, =CFG_MDCNFG_VAL<br /> bic r2, r2, #(MDCNFG_DE0 | MDCNFG_DE1)<br /> bic r2, r2, #(MDCNFG_DE2 | MDCNFG_DE3)<br /> str r2, [r1, #MDCNFG_OFFSET]<br /><br /> @ldr r2, = CFG_MDREFR_VAL<br /> @str r2, [r1, #MDREFR_OFFSET]<br />初始化内存控制器 Step 5 @ Step 5<br /> @ pause for 200 uSecs<br /> @<br /> ldr r3, =OSCR @ reset the OS Timer Count to zero<br /> mov r2, #0<br /> str r2, [r3]<br /> ldr r4, =0x300 @ really 0x2E1 is about 200usec, so 0x300 should be plenty ——3.25MHz clock<br />1:<br /> ldr r2, [r3] /* r2读OS Timer Count*/<br /> cmp r4, r2 /* 比较OS Timer Count和r4 */<br /> bgt 1b /* 如果时间没到就循环 */<br />初始化内存控制器 Step 6<br /> @ Step 6<br /> @ Disable XScale Data Cache<br /> mov r0, #0x78 @turn everything off<br /> mcr p15, 0, r0, c1, c0, 0 @(caches off, MMU off, etc.) /* 设置协处理器P15 */<br />初始化内存控制器 Step 7 - 11<br /> @ Step 7<br /> @ Access memory *not yet enabled* for CBR refresh cycles (8) *NOTE: hardware reset only<br /> @ - CBR is generated for all banks<br /><br /> ldr r2, =CFG_DRAM_BASE<br /> str r2, [r2]<br /> str r2, [r2]<br /> str r2, [r2]<br /> str r2, [r2]<br /> str r2, [r2]<br /> str r2, [r2]<br /> str r2, [r2]<br /> str r2, [r2]<br /><br /> @ Step 8<br /> @ Enable data cache<br /><br /> @ Step 9<br /> @ Enable SDRAM<br /><br /> @fetch current mdcnfg value<br /> ldr r3, [r1, #MDCNFG_OFFSET]<br /> orr r3, r3, #MDCNFG_DE0 /* enable sdram bank0 */<br /><br /> @write back mdcnfg, enabling the sdram bank(s)<br /> str r3, [r1, #MDCNFG_OFFSET]<br /><br /> @ Step 10<br /> @ write mdmrs —— SDRAM Mode Register Set Configuration Register<br /> @<br /> ldr r2, =CFG_MDMRS_VAL<br /> str r2, [r1, #MDMRS_OFFSET]<br /><br /> @ Step 11<br /> @ Enable MDREFR[APD] optionally<br /> ldr r2, =CFG_MDREFR_VAL<br /> str r2, [r1, #MDREFR_OFFSET]<br />Done Memory Init mem_init_done:<br /><br /> @********************************************************************<br /> @ Disable (mask) all interrupts at the interrupt controller<br /> @<br /><br /> @ clear the interrupt level register (use IRQ, not FIQ)<br /> @<br /> mov r1, #0<br /> ldr r2, =ICLR<br /> str r1, [r2]<br /><br /> @ Set interrupt mask register<br /> @<br /> ldr r1, =CFG_ICMR_VAL /* set ICMR = 0, no interrupts enabled */<br /> ldr r2, =ICMR<br /> str r1, [r2]<br /><br /> @ ********************************************************************<br /> @ Disable the peripheral clocks, and set the core clock<br /> @<br /><br /> @ Turn Off ALL on-chip peripheral clocks for re-configuration<br /> @<br /> ldr r1, =CKEN /*clock enable register */<br /> mov r2, #0<br /> str r2, [r1]<br /><br /> @ set core clocks<br /> @<br /> ldr r1, =CCCR /* core clock configuration register */<br /> ldr r2, [r1, #0]<br /> ldr r3, =(CCCR_L_MASK | CCCR_2N_MASK)<br /> bic r2, r2, r3<br /> /* Run-Mode-to-Oscillator Ratio (L) creates the nominal run mode frequency by multiplying the 13-MHz processor oscillator by L. */<br /> /* Turbo-Mode-to-Run-Mode Ratio (N) creates the nominal turbo-mode frequency by multiplying the run-mode frequency by N. */<br /> /* core freq: Normal 208MHz, Turbo 312MHz */<br /> ldr r3, =(16 | 3<<7) /* Turbo-Mode-to-Run-Mode Ratio, N = 3/2 */<br /> orr r2, r2, r3 /* Run-Mode-to-Oscillator Ratio = 16*13 MHz, */<br /> str r2, [r1]<br /><br />#ifdef ENABLE32KHZ<br /> @ enable the 32Khz oscillator for RTC and PowerManager<br /> @<br /> ldr r1, =OSCC /* oscillator configuration register */<br /> mov r2, #OSCC_OON /* 32.768kHz OON (write-once only bit) */<br /> str r2, [r1]<br /><br /> @ NOTE: spin here until OSCC.OOK get set,<br /> @ meaning the PLL has settled.<br /> @<br />60:<br /> ldr r2, [r1]<br /> ands r2, r2, #1 /* r2 = r2 & 0x1, 取出最低位数据 */<br /> beq 60b<br />#endif<br /><br /> @ Turn on needed clocks<br /> @<br /> ldr r1, =CKEN<br /> ldr r2, =CFG_CKEN_VAL<br /> str r2, [r1]<br />lowlevel_init完成 mov pc, r10 /* 恢复链接寄存器的值到PC,返回start.S调用lowlevel_init处继续执行 */<br /><br />@ End lowlevel_init<br /><br /> <br /> <br /> |
|