Chinaunix首页 | 论坛 | 博客
  • 博客访问: 439475
  • 博文数量: 123
  • 博客积分: 2686
  • 博客等级: 少校
  • 技术积分: 1349
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-23 22:11
文章分类
文章存档

2012年(3)

2011年(10)

2010年(100)

2009年(10)

我的朋友

分类: LINUX

2009-12-31 17:26:09

1. 头文件。
  • common.h是所有体系结构通用的头文件,里面主要声明了在u-boot第二个阶段用到的函数,并且根据config.h 里面定义的宏,选择性地包含一些头文件。
  • config.h文件是make _config生成的头文件,里面包含了与你开发板相关的头文件,这些头文件里面定义的宏作为开关的作用条件编译代码。比如,输入make smdk2410_config,将生成头文件config.h,config.h 的内容为:#include 和#include 。所以,移植的话,主要就是对smdk2410.h进行修改。

#include <common.h>
#include <config.h>


2. 中断向量表

  • 理解语句:_fiq:  .word fiq,表示告诉编译器,申请一个空间,名字为_fiq, 并把标号fiq的地址放在 _fiq这个空间里面。当执行:ldr pc,_fiq ,就把_fiq这个空间的内容复制到pc中。其他的语句相同的理解。
  •  .balignl 16,0xdeadbeef ,表示16字节对齐,当超过oxdeadeef时,就不理会这个规则。

.globl _start
_start:    b    start_code
    ldr    pc, _undefined_instruction
    ldr    pc, _software_interrupt
    ldr    pc, _prefetch_abort
    ldr    pc, _data_abort
    ldr    pc, _not_used
    ldr    pc, _irq
    ldr    pc, _fiq

_undefined_instruction:    .word undefined_instruction
_software_interrupt:    .word software_interrupt
_prefetch_abort:    .word prefetch_abort
_data_abort:        .word data_abort
_not_used:        .word not_used
_irq:            .word irq
_fiq:            .word fiq

    .balignl 16,0xdeadbeef


3. 定义了一些标签
  • _TEXT_BASE 告诉编译器程序执行的基地址是TEXT_BASE(在board\smdk2410\config.mk中定义)。
  • 定义了一个外部可以使用的标签,_armboot_start,并赋值为_start这个标号的地址._start的值可以通过make产生的u-boot.map查出来。注意:_armboot_start这个标号所在地址,和这个地址存放的值的区别哦。
  • _bss_start标签,存放的值是的整个u-boot有用代码段的末地址,搬运代码段为:[_start,__bss_start].__bss_start可以通过u-boot.map查出来的。
 

_TEXT_BASE:
    .word    TEXT_BASE

.globl _armboot_start
_armboot_start:
    .word _start

/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start
_bss_start:
    .word __bss_start

.globl _bss_end
_bss_end:
    .word _end

#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
    .word    0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
    .word 0x0badc0de
#endif


4. 设置cpu为 svc模式。真正的开始代码。

start_code:
    /*
     * set the cpu to SVC32 mode
     */
    mrs    r0, cpsr
    bic    r0, r0, #0x1f
    orr    r0, r0, #0xd3
    msr    cpsr, r0


5. LED灯的初始化。移植完全可以去掉

    bl    coloured_LED_init
    bl    red_LED_on


6. CONFIG_AT91RM9200DK , CONFIG_AT91RM9200EK. 如果是这两种体系结构,那么重定位异常向量表。

#if    defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
    /*
     * relocate exception table
     */
    ldr    r0, =_start
    ldr    r1, =0x0
    mov    r2, #16
copyex:
    subs    r2, r2, #1
    ldr    r3, [r0], #4
    str    r3, [r1], #4
    bne    copyex
#endif


7. CONFIG_S3C2400 , CONFIG_S3C2410. 此处是移植到S3C2440重点修改的代码。

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
    /* turn off the watchdog */

# if defined(CONFIG_S3C2400)
# define pWTCON    0x15300000
# define INTMSK    0x14400008    /* Interupt-Controller base addresses */
# define CLKDIVN    0x14800014    /* clock divisor register */
#else
# define pWTCON    0x53000000
# define INTMSK    0x4A000008    /* Interupt-Controller base addresses */
# define INTSUBMSK    0x4A00001C
# define CLKDIVN    0x4C000014    /* clock divisor register */
# endif

    ldr    r0, =pWTCON
    mov    r1, #0x0
    str    r1, [r0]

    /*
     * 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

    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr    r0, =CLKDIVN
    mov    r1, #3
    str    r1, [r0]
#endif    /* CONFIG_S3C2400 || CONFIG_S3C2410 */


8. 关闭看门狗

    ldr    r0, =pWTCON
    mov    r1, #0x0
    str    r1, [r0]


9. 关闭中断

    /*
     * 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


10. 设置时钟频率

    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz ! */
    ldr    r0, =CLKDIVN
    mov    r1, #3
    str    r1, [r0]
#endif    /* CONFIG_S3C2400 || CONFIG_S3C2410 */


11. cpu初始化。CONFIG_SKIP_LOWLEVEL_INIT

    /*
     * we do sys-critical inits only at reboot,
     * not when booting from ram!
     */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl    cpu_init_crit
#endif


12. cpu_init_crit; CONFIG_SKIP_LOWLEVEL_INIT.调用了函数lowlevel_init。
 

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
    /*
     * 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 */

    /*
     * 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

    /*
     * 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 */

13. lowlevel_init在文件board/samsung/smdk2410/lowlevel_init.S里面定义。完成内存的初始化。

#include <config.h>
#include <version.h>
/* some parameters for the board */
/*
 * Taken from linux/arch/arm/boot/compressed/head-s3c2410.S
 */

#define BWSCON    0x48000000

/* BWSCON */
#define DW8            (0x0)
#define DW16            (0x1)
#define DW32            (0x2)
#define WAIT            (0x1<<2)
#define UBLB            (0x1<<3)

#define B1_BWSCON        (DW32)
#define B2_BWSCON        (DW16)
#define B3_BWSCON        (DW16 + WAIT + UBLB)
#define B4_BWSCON        (DW16)
#define B5_BWSCON        (DW16)
#define B6_BWSCON        (DW32)
#define B7_BWSCON        (DW32)

/* BANK0CON */
#define B0_Tacs            0x0    /* 0clk */
#define B0_Tcos            0x0    /* 0clk */
#define B0_Tacc            0x7    /* 14clk */
#define B0_Tcoh            0x0    /* 0clk */
#define B0_Tah            0x0    /* 0clk */
#define B0_Tacp            0x0
#define B0_PMC            0x0    /* normal */

/* BANK1CON */
#define B1_Tacs            0x0    /* 0clk */
#define B1_Tcos            0x0    /* 0clk */
#define B1_Tacc            0x7    /* 14clk */
#define B1_Tcoh            0x0    /* 0clk */
#define B1_Tah            0x0    /* 0clk */
#define B1_Tacp            0x0
#define B1_PMC            0x0

#define B2_Tacs            0x0
#define B2_Tcos            0x0
#define B2_Tacc            0x7
#define B2_Tcoh            0x0
#define B2_Tah            0x0
#define B2_Tacp            0x0
#define B2_PMC            0x0

#define B3_Tacs            0x0    /* 0clk */
#define B3_Tcos            0x3    /* 4clk */
#define B3_Tacc            0x7    /* 14clk */
#define B3_Tcoh            0x1    /* 1clk */
#define B3_Tah            0x0    /* 0clk */
#define B3_Tacp            0x3 /* 6clk */
#define B3_PMC            0x0    /* normal */

#define B4_Tacs            0x0    /* 0clk */
#define B4_Tcos            0x0    /* 0clk */
#define B4_Tacc            0x7    /* 14clk */
#define B4_Tcoh            0x0    /* 0clk */
#define B4_Tah            0x0    /* 0clk */
#define B4_Tacp            0x0
#define B4_PMC            0x0    /* normal */

#define B5_Tacs            0x0    /* 0clk */
#define B5_Tcos            0x0    /* 0clk */
#define B5_Tacc            0x7    /* 14clk */
#define B5_Tcoh            0x0    /* 0clk */
#define B5_Tah            0x0    /* 0clk */
#define B5_Tacp            0x0
#define B5_PMC            0x0    /* normal */

#define B6_MT            0x3    /* SDRAM */
#define B6_Trcd            0x1
#define B6_SCAN            0x1    /* 9bit */

#define B7_MT            0x3    /* SDRAM */
#define B7_Trcd            0x1    /* 3clk */
#define B7_SCAN            0x1    /* 9bit */

/* REFRESH parameter */
#define REFEN            0x1    /* Refresh enable */
#define TREFMD            0x0    /* CBR(CAS before RAS)/Auto refresh */
#define Trp            0x0    /* 2clk */
#define Trc            0x3    /* 7clk */
#define Tchr            0x2    /* 3clk */
#define REFCNT            1113    /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */
/**************************************/

_TEXT_BASE:
    .word    TEXT_BASE

.globl lowlevel_init
lowlevel_init:
    /* memory control configuration */
    /* make r0 relative the current location so that it */
    /* reads SMRDATA out of FLASH rather than memory ! */
    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 0x32
    .word 0x30
    .word 0x30


14. 回到 bl cpu_init_crit后面的代码。 CONFIG_SKIP_RELOCATE_UBOOT,首先判断是在flash中执行还是在RAM中执行,如果在flash中执行,那么就搬运代码到RAM中。adr r0,_start;表示取出 _start标号代表的地址,放到r0中。ldr r1, _TEXT_BASE;表示取出_TEXT_BASE标号代表的地址 存储的值,放到r1中。
 

#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            

    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 */


15. 建立栈。画出内存分布图,就一目了然了。

stack_setup:
    ldr    r0, _TEXT_BASE      /* upper 128 KiB: relocated uboot */
    sub    r0, r0, #CONFIG_SYS_MALLOC_LEN    /* malloc area */
    sub    r0, r0, #CONFIG_SYS_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 */


16. 初始化bss段为0.

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


17. 跳到RAM中去执行。

    ldr    pc, _start_armboot
_start_armboot:    .word start_armboot


18. 中断相关代码。CONFIG_USE_IRQ

/*
 *************************************************************************
 *
 * Interrupt handling
 *
 *************************************************************************
 */

@
@ IRQ stack frame.
@
#define S_FRAME_SIZE    72

#define S_OLD_R0    68
#define S_PSR        64
#define S_PC        60
#define S_LR        56
#define S_SP        52

#define S_IP        48
#define S_FP        44
#define S_R10        40
#define S_R9        36
#define S_R8        32
#define S_R7        28
#define S_R6        24
#define S_R5        20
#define S_R4        16
#define S_R3        12
#define S_R2        8
#define S_R1        4
#define S_R0        0

#define MODE_SVC    0x13
#define I_BIT        0x80

/*
 * use bad_save_user_regs for abort/prefetch/undef/swi ...
 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
 */

    .macro    bad_save_user_regs
    sub    sp, sp, #S_FRAME_SIZE
    stmia    sp, {r0 - r12}            @ Calling r0-r12
    ldr    r2, _armboot_start
    sub    r2, r2, #(CONFIG_STACKSIZE)
    sub    r2, r2, #(CONFIG_SYS_MALLOC_LEN)
    /* set base 2 words into abort stack */
    sub    r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)
    ldmia    r2, {r2 - r3}            @ get pc, cpsr
    add    r0, sp, #S_FRAME_SIZE        @ restore sp_SVC

    add    r5, sp, #S_SP
    mov    r1, lr
    stmia    r5, {r0 - r3}            @ save sp_SVC, lr_SVC, pc, cpsr
    mov    r0, sp
    .endm

    .macro    irq_save_user_regs
    sub    sp, sp, #S_FRAME_SIZE
    stmia    sp, {r0 - r12}            @ Calling r0-r12
    add    r7, sp, #S_PC
    stmdb    r7, {sp, lr}^            @ Calling SP, LR
    str    lr, [r7, #0]            @ Save calling PC
    mrs    r6, spsr
    str    r6, [r7, #4]            @ Save CPSR
    str    r0, [r7, #8]            @ Save OLD_R0
    mov    r0, sp
    .endm

    .macro    irq_restore_user_regs
    ldmia    sp, {r0 - lr}^            @ Calling r0 - lr
    mov    r0, r0
    ldr    lr, [sp, #S_PC]            @ Get PC
    add    sp, sp, #S_FRAME_SIZE
    /* return & move spsr_svc into cpsr */
    subs    pc, lr, #4
    .endm

    .macro get_bad_stack
    ldr    r13, _armboot_start        @ setup our mode stack
    sub    r13, r13, #(CONFIG_STACKSIZE)
    sub    r13, r13, #(CONFIG_SYS_MALLOC_LEN)
    /* reserve a couple spots in abort stack */
    sub    r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8)

    str    lr, [r13]            @ save caller lr / spsr
    mrs    lr, spsr
    str    lr, [r13, #4]

    mov    r13, #MODE_SVC            @ prepare SVC-Mode
    @ msr    spsr_c, r13
    msr    spsr, r13
    mov    lr, pc
    movs    pc, lr
    .endm

    .macro get_irq_stack            @ setup IRQ stack
    ldr    sp, IRQ_STACK_START
    .endm

    .macro get_fiq_stack            @ setup FIQ stack
    ldr    sp, FIQ_STACK_START
    .endm

/*
 * exception handlers
 */
    .align 5
undefined_instruction:
    get_bad_stack
    bad_save_user_regs
    bl    do_undefined_instruction

    .align    5
software_interrupt:
    get_bad_stack
    bad_save_user_regs
    bl    do_software_interrupt

    .align    5
prefetch_abort:
    get_bad_stack
    bad_save_user_regs
    bl    do_prefetch_abort

    .align    5
data_abort:
    get_bad_stack
    bad_save_user_regs
    bl    do_data_abort

    .align    5
not_used:
    get_bad_stack
    bad_save_user_regs
    bl    do_not_used

#ifdef CONFIG_USE_IRQ

    .align    5
irq:
    get_irq_stack
    irq_save_user_regs
    bl    do_irq
    irq_restore_user_regs

    .align    5
fiq:
    get_fiq_stack
    /* someone ought to write a more effiction fiq_save_user_regs */
    irq_save_user_regs
    bl    do_fiq
    irq_restore_user_regs

#else

    .align    5
irq:
    get_bad_stack
    bad_save_user_regs
    bl    do_irq

    .align    5
fiq:
    get_bad_stack
    bad_save_user_regs
    bl    do_fiq

#endif


总结start.S执行动作:
  • 设置cpu为 svc模式
  • 关闭看门狗
  • 关闭中断
  • 设置时钟频率
  • cpu初始化
  • 搬运代码到RAM中
  • 初始化bss段为0
  • 跳到RAM中去执行
  • (中断处理相关)

移植到s3c2440时,重点考虑以上几个动作,着重考察 s3c2440和s3c2410的不同之处;

本段代码不支持从NAND FLASH启动,如果要从NAND启动,就要在 搬运代码处做文章,不是直接从NOR FLASH中复制代码到RAM,而是从NAND读取代码到RAM中;

手动跟踪代码执行的过程,记录下 2440所需要增加、定义、配置参数的宏,以便在smdk2440.h中进行修改。一般的做法是,是smdk2440.h从smdk2410复制而来,在这基础上对宏进行修改。

 

后记:下一篇博客将是具体的移植过程,具体的修改过程。

欢迎转载,但注明出处。
阅读(1374) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~