關於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將自己拷貝到了內存, 所以正常運行.









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