Chinaunix首页 | 论坛 | 博客
  • 博客访问: 353392
  • 博文数量: 90
  • 博客积分: 2017
  • 博客等级: 大尉
  • 技术积分: 615
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-19 08:10
文章分类

全部博文(90)

文章存档

2012年(4)

2011年(74)

2010年(11)

2009年(1)

分类: 嵌入式

2011-05-19 21:32:39

U-Boot源代码阅读笔记(一)和(二) —— 对start.S的分析
本文主要分析与U-Boot启动过程相关的汇编代码cpu/pxa/start.S,目标平台以PXA270为例。
/* armboot - Startup Code for XScale */
.globl _start
_start: b    reset    /*跳转到reset标号执行*/
  • 设置cpu为superviser模式
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
  • 跳转到start_armboot执行
    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]
  • lowlevel_init完成
   mov   pc, r10    /* 恢复链接寄存器的值到PC,返回start.S调用lowlevel_init处继续执行 */

@ End lowlevel_init

阅读(1464) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~