关于uboot启动中地址的问题

c7e00000 <_start>:
c7e00000: ea000013 b c7e00054 <reset>
c7e00004: e59ff014 ldr pc, [pc, #20] ; c7e00020 <_undefined_instruction>
c7e00008: e59ff014 ldr pc, [pc, #20] ; c7e00024 <_software_interrupt>
c7e0000c: e59ff014 ldr pc, [pc, #20] ; c7e00028 <_prefetch_abort>
c7e00010: e59ff014 ldr pc, [pc, #20] ; c7e0002c <_data_abort>
c7e00014: e59ff014 ldr pc, [pc, #20] ; c7e00030 <_not_used>
c7e00018: e59ff014 ldr pc, [pc, #20] ; c7e00034 <_irq>
c7e0001c: e59ff014 ldr pc, [pc, #20] ; c7e00038 <_fiq>
c7e00020 <_undefined_instruction>:
c7e00020: c7e00200 .word 0xc7e00200
c7e00024 <_software_interrupt>:
c7e00024: c7e00260 .word 0xc7e00260
c7e00028 <_prefetch_abort>:
c7e00028: c7e002c0 .word 0xc7e002c0
c7e0002c <_data_abort>:
c7e0002c: c7e00320 .word 0xc7e00320
c7e00030 <_not_used>:
c7e00030: c7e00380 .word 0xc7e00380
c7e00034 <_irq>:
c7e00034: c7e003e0 .word 0xc7e003e0
c7e00038 <_fiq>:
c7e00038: c7e00440 .word 0xc7e00440
c7e0003c <_pad>:
c7e0003c: 12345678 .word 0x12345678
c7e00040 <_end_vect>:
c7e00040: c7e00000 .word 0xc7e00000
c7e00044 <_TEXT_PHY_BASE>:
c7e00044: 57e00000 .word 0x57e00000
c7e00048 <_armboot_start>:
c7e00048: c7e00000 .word 0xc7e00000
c7e0004c <_bss_start>:
c7e0004c: c7e34000 .word 0xc7e34000
c7e00050 <_bss_end>:
c7e00050: c7e48c54 .word 0xc7e48c54
c7e00054 <reset>:

一. 在start中开始
c7e00000 <_start>:
c7e00000: ea000013 b c7e00054 <reset>


1. 由于ARM体系结构(流水线的问题)(没有探讨)
所以PC = PC + 8

2.uboot刚开始在steppingstone(0x0c00 0000 ,s3c6410)中执行
所以pc = 0xc00 0000 + 8;

3. b指令是相对跳转(一共24位,其中第24位为符号位,所以一共能跳转 正负2^23 个字的距离, 即 正负 2^25 字节, 即正负32MB)

4. 当执行 b reset 之前时,pc = 0xc00 0008

接着跳转的距离由编译器自己算出来, 即:ea000013 中的13, 跳转 19个字

刚好跳转到 reset, 这时 pc 的值为 0xc00 0008 + 19 = 0xc00 001B

二. 如何让代码在内存中正常运行?

1.首先
int copy_uboot_to_ram (void)
{
int large_block = 0;
int i;
vu_char id;

        NAND_ENABLE_CE();
        NFCMD_REG = NAND_CMD_READID;
        NFADDR_REG =  0x00;


/* wait for a while */
        for (i=0; i<200; i++);
id = NFDATA8_REG;
id = NFDATA8_REG;


if (id > 0x80)
large_block = 1;


/* read NAND Block.
* 128KB ->240KB because of U-Boot size increase. by scsuh
* So, read 0x3c000 bytes not 0x20000(128KB).
*/
//CFG_PHY_UBOOT_BASE = 0x57e0 0000
return nandll_read_blocks(CFG_PHY_UBOOT_BASE, 0x3c000, large_block);
}

2.其次
#ifdef CONFIG_ENABLE_MMU
enable_mmu:
/* enable domain access */
ldr r5, =0x0000ffff
mcr p15, 0, r5, c3, c0, 0 @ load domain access register


/* Set the TTB register */
ldr r0, _mmu_table_base
ldr r1, =CFG_PHY_UBOOT_BASE //MEMORY_BASE_ADDRESS + 0x7e00000=0x57e00000
ldr r2, =0xfff00000
bic r0, r0, r2
orr r1, r0, r1
mcr p15, 0, r1, c2, c0, 0


/* Enable the MMU */
mmu_on:
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #1 /* Set CR_M to enable MMU */
mcr p15, 0, r0, c1, c0, 0
nop
nop
nop
nop
#endif


3.最后
/*******************************************************************************/
c7e0014c: e51ff004 ldr pc, [pc, #-4] ; c7e00150 <_start_armboot>

c7e00150 <_start_armboot>:
c7e00150: c7e03bbc .word 0xc7e03bbc

c7e00154 <_mmu_table_base>:
c7e00154: c7e30000 .word 0xc7e30000

1.由于ARM体系结构(流水线的问题)
所以PC = PC + 8

2.uboot刚开始在steppingstone(0x0c00 0000 ,s3c6410)中执行

此时 pc = 0xC00 0154

ldr pc, [pc, #-4] ===---===> ldr pc, [0xc00 0150];

执行完这条指令后 pc = 0xc7e0 3bbc;

由此可见ldr指令是绝对转移, 而这刚好是start_armboot的地址

/********************************************************************************/
0xc7e0 3bbc 怎样在内存中执行呢?
首先执行ldr pc, [pc, #-4] 后,cpu开始执行0xc7e0 3bbc地址处 的指令
当cpu取 地址时 ,由于之前已经开启了MMU, 即转换为物理地址.(内存中的物理地址)
即从内存中取指令,由于之前已经uboot将自己拷贝到了内存, 所以正常运行.









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章