##nand flash啓動
cpu無法給nand flash發送指令,因此無法從nand flash中取指令的。那麼上電後,爲啥依然可以從nand flash中啓動uboot呢?
1.硬件會自動將nand flash的代碼前4K拷貝到SRAM(片內內存,steppintstone)中。CPU從SRAM的0地址中執行代碼。如果uboot的代碼大於4K怎麼辦?uboot中前4K的代碼需要初始化nand flash,SDRAM,並將nand flash中整個uboot程序讀出來,拷貝到SDRAM的中。這個過程其實就是代碼重定位。
##nor flash啓動
nor flash是內存類結構,可以直接向內存一樣訪問的,但是無法像內存一樣寫。因此,當從nor flash啓動時,CPU會從nor flash的0地址開始執行指令,但是注意指令中只能讀取變量,而無法修改變量的值。所以,也需要把全局變量和靜態變量重定位到sdram中。
##程序各個代碼段
.text 代碼段
.data 數據段 (初始化的全局變量或者靜態局部變量)
rodata 只讀數據段(const全局變量)
bss段 (初始值爲0,未初始化的全局變量)
commen 註釋
其中bss段和commen 註釋不保存在bin文件中。
##關於lds的實驗
實驗代碼來自於韋東山的嵌入式課本源碼: hardware\i2c
鏈接腳本
SECTIONS {
. = 0x00000000;
.init : AT(0){ head.o init.o nand.o}
. = 0x30000000;
.text : AT(4096) { *(.text) }
.rodata ALIGN(4) : AT((LOADADDR(.text)+SIZEOF(.text)+3)&~(0x03)) {*(.rodata*)}
.data ALIGN(4) : AT((LOADADDR(.rodata)+SIZEOF(.rodata)+3)&~(0x03)) { *(.data) }
__bss_start = .;
.bss ALIGN(4) : { *(.bss) *(COMMON) }
__bss_end = .;
}
反彙編文件:
i2c_elf: file format elf32-littlearm
Disassembly of section .init:
00000000 <_start>:
0: ea000006 b 20 <Reset>
00000004 <HandleUndef>:
4: eafffffe b 4 <HandleUndef>
00000008 <HandleSWI>:
8: eafffffe b 8 <HandleSWI>
0000000c <HandlePrefetchAbort>:
c: eafffffe b c <HandlePrefetchAbort>
00000010 <HandleDataAbort>:
…………
5a0: 00696261 .word 0x00696261
5a4: 00000501 .word 0x00000501
5a8: 00000000 .word 0x00000000
Disassembly of section .text: #代碼段的開始,如lds腳本,開始地址爲30000000。之前存放的是初始化段,包含head.o init.o nand.o 三個文件的代碼
30000000 <init_irq>:
30000000: e59f2030 ldr r2, [pc, #48] ; 30000038 <init_irq+0x38>
30000004: e59f1030 ldr r1, [pc, #48] ; 3000003c <init_irq+0x3c>
30000008: e28230c8 add r3, r2, #200 ; 0xc8
3000000c: e4821004 str r1, [r2], #4
30000010: e1520003 cmp r2, r3
30000014: 1afffffc bne 3000000c <init_irq+0xc>
30000018: e59f3020 ldr r3, [pc, #32] ; 30000040 <init_irq+0x40>
3000001c: e3a0144a mov r1, #1241513984 ; 0x4a000000
30000020: e502305c str r3, [r2, #-92]
##lds文件解析
SECTIONS {
. = 0x00000000;
.init : AT(0){ head.o init.o nand.o}
. = 0x40000000; ##表示之後的各個段彙編代碼的絕對路徑。指令中絕對跳轉使用的就是這個地址。對應於運行地址、鏈接地址。
.text : AT(2048) { *(.text) } ##AT表示這個段放在bin文件偏移2048的位置。可以用ue打開文件,在2048地址處查看到對應的機器碼。對應於加載地址。
.rodata ALIGN(4) : AT((LOADADDR(.text)+SIZEOF(.text)+3)&~(0x03)) {*(.rodata*)}
.data ALIGN(4) : AT((LOADADDR(.rodata)+SIZEOF(.rodata)+3)&~(0x03)) { *(.data) }
__bss_start = .;
.bss ALIGN(4) : { *(.bss) *(COMMON) }
__bss_end = .;
}