单片机
返回首页

学习ARM开发(8)

2024-11-14 来源:cnblogs

上一次看了数据区,这次要看从引导那里跳到这里执行时,运行什么东西了。
/*
* 实际运行的复位代码。从一开始运行的代码,就跳到这里运行。
*/

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


/*
*************************************************************************
*
* CPU_init_critical临界区寄存器
*
* 设置一些重要的寄存器,并进行内存测试。
*
*
*************************************************************************
*/

#define INTCON (0x01c00000+0x200000) /* 中断控制器 */
#define INTMSK (0x01c00000+0x20000c) /* 中断控制屏蔽寄存器 */
#define LOCKTIME (0x01c00000+0x18000c)
#define PLLCON (0x01c00000+0x180000)
#define CLKCON (0x01c00000+0x180004)
#define WTCON (0x01c00000+0x130000)
cpu_init_crit:
        /* 关闭看门狗 */
        ldr         r0, =WTCON
        ldr        r1, =0x0
        str        r1, [r0]

        /*
         * 清除所有中断位,设置INTMRs实现。
         */
        ldr        r1,=INTMSK
        ldr        r0, =0x03fffeff
        str        r0, [r1]

        ldr        r1, =INTCON
        ldr        r0, =0x05
        str        r0, [r1]

        /* 设置时钟控制寄存器 */
        ldr        r1, =LOCKTIME
        ldrb        r0, =800
        strb        r0, [r1]

        /* 设置锁相环,控制CPU运行速度。 */
        ldr        r1, =PLLCON

#if CONFIG_S3C44B0_CLOCK_SPEED==66
        ldr        r0, =0x34031         /* 66MHz (Quartz=11MHz) */
#elif CONFIG_S3C44B0_CLOCK_SPEED==75
        ldr        r0, =0x610c1 /*B2: Xtal=20mhz Fclk=75MHz  */
#else
# error CONFIG_S3C44B0_CLOCK_SPEED undefined
#endif

        str        r0, [r1]

        ldr        r1,=CLKCON
        ldr        r0, =0x7ff8
        str        r0, [r1]

        /* 调用子函数返回 */
        mov        pc, lr


/*************************************************/
/*        实际的中断向量表        */
/*************************************************/
real_vectors:
        b        reset
        b        undefined_instruction
        b        software_interrupt
        b        prefetch_abort
        b        data_abort
        b        not_used
        b        irq
        b        fiq

/*************************************************/

undefined_instruction:
        mov        r6, #3
        b        reset

software_interrupt:
        mov        r6, #4
        b        reset

prefetch_abort:
        mov        r6, #5
        b        reset

data_abort:
        mov        r6, #6
        b        reset

not_used:
        /* we *should* never reach this */
        mov        r6, #7
        b        reset

irq:
        mov        r6, #8
        b        reset

fiq:
        mov        r6, #9
        b        reset

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • PIC单片机控制的遥控防盗报警器电路

  • 红外线探测报警器

  • 短波AM发射器电路设计图

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 开关电源的基本组成及工作原理

  • 带有短路保护系统的5V直流稳压电源电路图

    相关电子头条文章