ARM裸機全集擴充套件--SRAM內部重定位程式碼示例

毛褲先生_2發表於2020-12-09

注:此程式碼來自朱老師ARM裸機課程中,這裡貼出來方便檢視

Makefile

led.bin: start.o led.o
	arm-linux-ld -Tlink.lds -o led.elf $^
	arm-linux-objcopy -O binary led.elf led.bin
	arm-linux-objdump -D led.elf > led_elf.dis
	gcc mkv210_image.c -o mkx210
	./mkx210 led.bin 210.bin
	
%.o : %.S
	arm-linux-gcc -o $@ $< -c -nostdlib

%.o : %.c
	arm-linux-gcc -o $@ $< -c -nostdlib

clean:
	rm *.o *.elf *.bin *.dis mkx210 -f

link.lds

SECTIONS
{
	. = 0xd0024000;
	
	.text : {
		start.o
		* (.text)
	}
    		
	.data : {
		* (.data)
	}
	
	bss_start = .; 
	.bss : {
		* (.bss)
	}
	
	bss_end  = .;	
}

start.S

/*
 * 檔名:	led.s	
 * 作者:	朱老師
 * 描述:	演示重定位(在SRAM內部重定位)
 */

#define WTCON		0xE2700000

#define SVC_STACK	0xd0037d80

.global _start					// 把_start連結屬性改為外部,這樣其他檔案就可以看見_start了
_start:
	// 第1步:關看門狗(向WTCON的bit5寫入0即可)
	ldr r0, =WTCON
	ldr r1, =0x0
	str r1, [r0]
	
	// 第2步:設定SVC棧
	ldr sp, =SVC_STACK
	
	// 第3步:開/關icache
	mrc p15,0,r0,c1,c0,0;			// 讀出cp15的c1到r0中
	//bic r0, r0, #(1<<12)			// bit12 置0  關icache
	orr r0, r0, #(1<<12)			// bit12 置1  開icache
	mcr p15,0,r0,c1,c0,0;
	
	// 第4步:重定位
	// adr指令用於載入_start當前執行地址
	adr r0, _start  		// adr載入時就叫短載入		
	// ldr指令用於載入_start的連結地址:0xd0024000
	ldr r1, =_start // ldr載入時如果目標暫存器是pc就叫長跳轉,如果目標暫存器是r1等就叫長載入	
	// bss段的起始地址
	ldr r2, =bss_start	// 就是我們重定位程式碼的結束地址,重定位只需重定位程式碼段和資料段即可
	cmp r0, r1			// 比較_start的執行時地址和連結地址是否相等
	beq clean_bss		// 如果相等說明不需要重定位,所以跳過copy_loop,直接到clean_bss
						// 如果不相等說明需要重定位,那麼直接執行下面的copy_loop進行重定位
						// 重定位完成後繼續執行clean_bss。

// 用匯編來實現的一個while迴圈
copy_loop:
	ldr r3, [r0], #4    // 源
	str r3, [r1], #4	// 目的   這兩句程式碼就完成了4個位元組內容的拷貝
	cmp r1, r2			// r1和r2都是用ldr載入的,都是連結地址,所以r1不斷+4總能等於r2
	bne copy_loop

	// 清bss段,其實就是在連結地址處把bss段全部清零
clean_bss:
	ldr r0, =bss_start					
	ldr r1, =bss_end
	cmp r0, r1				// 如果r0等於r1,說明bss段為空,直接下去
	beq run_on_dram			// 清除bss完之後的地址
	mov r2, #0
clear_loop:
	str r2, [r0], #4		// 先將r2中的值放入r0所指向的記憶體地址(r0中的值作為記憶體地址),
	cmp r0, r1				// 然後r0 = r0 + 4
	bne clear_loop

run_on_dram:	
	// 長跳轉到led_blink開始第二階段
	ldr pc, =led_blink				// ldr指令實現長跳轉
	
	// 從這裡之後就可以開始呼叫C程式了
	//bl led_blink					// bl指令實現短跳轉
	
// 彙編最後的這個死迴圈不能丟
	b .

 

相關文章