新闻  |   论坛  |   博客  |   在线研讨会
如何开发arm(3)
tvro_china | 2007-12-21 18:13:18    阅读:3414   发布文章

/******************************************************************
* 启动代码。
** 如果不作内存初始化,就只建立堆栈,重新定位代码到RAM位置。
* 然后就可以跳到第二阶段的代码运行了。
**********************************************************************/

/* 保存变量的数据区 */
_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

上面这段代码,主要保存一些全局变量,用于BOOT程序从FLASH拷贝到RAM,或者其它的使用。还有一些变量的长度是

通过连接脚本里得到,实际上由编译器算出来的。

看了数据区,这次要看从引导那里跳到这里执行时,运行什么东西了。
/** 实际运行的复位代码。从一开始运行的代码,就跳到这里运行。*/
reset:
       /* * 设置cpu运行在SVC32模式。*/
        mrs        r0,cpsr
        bic        r0,r0,#0x1f
       orr        r0,r0,#0x13
       msr        cpsr,r0

具体分析如下:
/** 实际运行的复位代码。从一开始运行的代码,就跳到这里运行。*/

reset:
        /** 设置cpu运行在SVC32模式。S3C44B0共有7种模式。   */
       mrs        r0,cpsr
取得当前程序状态寄存器cpsr到r0。
        bic        r0,r0,#0x1f
这里使用位清除指令,把中断全部清除,只置位模式控制位。
        orr        r0,r0,#0x13
计算为超级保护模式。
        msr        cpsr,r0
设置cpsr为超级保护模式。
通过设置ARM的CPSR寄存器,让CPU运行在操作系统模式,为后面进行其它操作作好准备了。后面的代码如下:
/*       * 当是从FLASH启动时,就要进行内存测试,当
         * 是从RAM启动时,一般就是开发本源程序时,就
         * 可以跳过。
         *
         */
#ifdef CONFIG_INIT_CRITICAL
        bl        cpu_init_crit
       /*
         * 在重新定位之前,要进行RAM访问时间测试,因为每个开发
         * 都是不一样的。
         * 可以在文件memsetup.S里看到它的说明。        
        */
        bl        memsetup
#endif

/* 进行重定位 */
relocate:        /* 重定位Boot代码到RAM内存,比如从FLASH移到RAM */
adr      r0, _start                /* 把_start的相对地址移到r0    */
ldr     r1, _TEXT_BASE    /* 把_TEXT_BASE地址,就是BOOT在RAM中运行地址 */
cmp     r0, r1         /*  比较两个地址是否相同,如果相同,就已经在RAM运行,否则就是FLASH中运行。*/
       beq     stack_setup

  /* 是在FLASH中运行,要把FLASH中的BOOT代码移到RAM中,然后再运行. */
       ldr        r2, _armboot_start
       ldr        r3, _bss_start
       sub        r2, r3, r2                /* r2保存引导代码大小    */
       add        r2, r0, r2                /* r2保存引导代码最后地址         */
copy_loop:
        ldmia        r0!, {r3-r10}                /* 从源地址[r0]读取8个字节到寄存器,每读一个就更新一

次r0地址 */
        stmia        r1!, {r3-r10}                /* 拷贝寄存器r3-r10的值保存到 [r1]指明的地址,每写一

个字节,就增加1.    */
        cmp        r0, r2                        /* 判断是否拷贝到[r2]地址,就是引导代码结束位置。   */
        ble        copy_loop       /* 循环拷贝 */
/*拷贝中断向量表,实际是建立起二级中断向量表,当CPU中断时,先运行FLASH中断,接着就转移到实际中向表执行

中断程序。*/
        adr        r0, real_vectors
        add        r2, r0, #1024
        ldr        r1, =0x0c000000
        add        r1, r1, #0x08
vector_copy_loop:
        ldmia        r0!, {r3-r10}
        stmia        r1!, {r3-r10}
        cmp        r0, r2
        ble        vector_copy_loop
        /* 建立起堆栈        */
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    */
        ldr        pc, _start_armboot /* 已经准备好了堆栈,就可跳到C写的代码里,由于我的代码是ARM,就是

跳到lib_arm\board.c(208):void start_armboot (void)中运行。 */

_start_armboot:        .word start_armboot

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
与快乐握手
最近文章
怎样做一块好的PCB板
2009-05-18 17:14:25
ARM入门
2009-05-18 17:10:18
推荐文章
最近访客