日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

tiny4412 裸机程序 六、重定位代码到IRAM+0x8000

發(fā)布時(shí)間:2023/12/14 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 tiny4412 裸机程序 六、重定位代码到IRAM+0x8000 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、重定向

對(duì)于程序而言,我們需要理解兩個(gè)概念,一是程序當(dāng)前所處的地址,即程序在運(yùn)行時(shí),所處的當(dāng)前地址;二是程序的鏈接地址,即程序運(yùn)行時(shí)應(yīng)該位于的運(yùn)行地址。編譯程序時(shí),可以指定程序的鏈接地址。對(duì)于Tiny4412而言,啟動(dòng)時(shí)只會(huì)從MMC/sd等啟動(dòng)設(shè)備中拷貝前16K的代碼到IRAM中,那么當(dāng)我們的程序超過(guò)16K怎么辦?那就需要我們?cè)谇?6K的代碼中將整個(gè)程序完完整整地拷貝到DRAM等其他更大存儲(chǔ)空間,然后再跳轉(zhuǎn)到DRAM中繼續(xù)運(yùn)行我們的代碼,這個(gè)拷貝然后跳轉(zhuǎn)的過(guò)程就叫重定位。

本章中我們主要學(xué)習(xí)如何重定位,但是并不會(huì)涉如何使用到DRAM,而是簡(jiǎn)單地將代碼從IRAM的0x02020010處拷貝到IRAM的0x02028000處,然后跳轉(zhuǎn)到0x02028000處繼續(xù)運(yùn)行我們的代碼。

二、程序說(shuō)明

完整代碼見(jiàn)目錄5_link_0x8000,該目錄下的代碼與上一章的代碼的差別在于start.S和使用了

鏈接腳本link.lds,我們首先分析link.lds。

1. link.lds

什么是鏈接腳本?鏈接腳本就是程序鏈接時(shí)的參考文件,其主要目的是描述如何把輸入文件中的段(SECTION)映射到輸出文件中,并控制輸出文件的存儲(chǔ)布局。鏈接腳本的基本命令式SECTIONS命令,一個(gè)SECTIONS命令內(nèi)部包含一個(gè)或多個(gè)段,段(SECTION)是鏈接腳本的基本單元,它表示輸入文件中的某個(gè)段是如何放置的。

鏈接腳本的標(biāo)準(zhǔn)格式如下:

SECTIONS

{

sections-command

sections-command

}

下面我們配合link.lds進(jìn)行具體講解:

SECTIONS

{

. = 0x02028000;

.text : {

start.o

* (.text)

}

.data : {

* (.data)

}

bss_start = .;

.bss : {

* (.bss)

}

bss_end = .;

}

1)? 在鏈接腳本中,單獨(dú)的點(diǎn)號(hào)(.)代表了當(dāng)前位置,. =0x02028000;表示程序的鏈接地址是00x02028000;

2)? link.lds中的.text 、 .data 、 .bss分別是text段、data段、bss段的段名(這些段名并不是固定的,是可以隨便起的)。.text 段包含的內(nèi)容是start.o 和其余代碼中所有的text段;.data段包含的內(nèi)容是代碼中所有的data段;.bss段包含的內(nèi)容是代碼中所有的bss段。

3)? bss_start和bss_end保存的是bss段的起始地址和結(jié)束地址,在start.S中會(huì)被用到。

下面解釋一下什么是data、text、bss段:

1)? data段:數(shù)據(jù)段(datasegment)通常是指用來(lái)存放程序中已初始化的全局變量的一塊內(nèi)存區(qū)域。數(shù)據(jù)段屬于靜態(tài)內(nèi)存分配。

2)? text段:代碼段通常是指用來(lái)存放程序執(zhí)行代碼的一塊內(nèi)存區(qū)域。這部分區(qū)域的大小在程序運(yùn)行前就已經(jīng)確定,并且內(nèi)存區(qū)域通常屬于只讀,某些架構(gòu)也允許代碼段為可寫(xiě),即允許修改程序。在代碼段中,也有可能包含一些只讀的常數(shù)變量,例如字符串常量等。

3)? bss段:指用來(lái)存放程序中未初始化的全局變量的一塊內(nèi)存區(qū)域。BSS是英文BlockStarted by Symbol的簡(jiǎn)稱。當(dāng)我們的程序有全局變量是,它是放在bss段的,由于全局變量默認(rèn)初始值都是0,所有我們需要手動(dòng)清bss段。

2. start.S

在start.S中,我們初始化時(shí)鐘后,增加了3個(gè)步驟:

第一步重定位,代碼如下:

// _start當(dāng)前所位于的地址

adr r0, _start??

// _start的鏈接地址

ldr r1, =_start??

ldr r2, =bss_start

cmp r0, r1

beq clean_bss

copy_loop:

ldr r3, [r0], #4

str r3, [r1], #4

cmp r1, r2

bne copy_loop

首先需要知道的是,adr指令獲取的值是代碼當(dāng)前位于的地址,而ldr指令獲取的值是代碼的鏈接地址。再來(lái)看代碼,代碼里首先獲得_start標(biāo)號(hào)的當(dāng)前地址(即0x02020010),然后獲取_start標(biāo)號(hào)的鏈接地址(即0x02028000),因?yàn)閎in文件中不需要保存bss段,所有拷貝的代碼長(zhǎng)度為bss_start的運(yùn)行地址-_start的運(yùn)行地址,使用copy_loop進(jìn)行拷貝。

?

第二步清bss,代碼如下:

ldr r0, =bss_start????????

ldr r1, =bss_end

cmp r0, r1

beq run_on_dram

mov r2, #0

clear_loop:

str r2, [r0], #4

cmp r0, r1

bne clear_loop

首先獲得bss段的起始地址(即bss_start),然后獲得bss段的結(jié)束地址(即bss_end),最后使用clear_loop將bss段所位于的內(nèi)存清0,bss_start和bss_end的定義位于link.lds。

第三步跳轉(zhuǎn),代碼如下:

run_on_dram:???

ldr pc, =main

由于ldr 指令獲取的是main函數(shù)的鏈接地址,所以執(zhí)行l(wèi)drpc, =main 后,程序就跳轉(zhuǎn)到

0x02020000+main函數(shù)的offset的地址處了。

三、完整的燒寫(xiě)過(guò)程

已將SD卡插入電腦,假設(shè)linux識(shí)別了SD卡,其識(shí)別號(hào)為sdb。執(zhí)行下面命令:

# chmod 777 –R 5_link_0x8000

# cd 5_link_0x8000

# make

# cd sd_fuse

# make

# ./ fast_fuse /dev/sdb

四、上電實(shí)驗(yàn)

將sd卡插入Tiny4412中,選擇sd卡啟動(dòng),然后上電,可以看到以下現(xiàn)象:

LED正常閃爍,該現(xiàn)象與前面章節(jié)的代碼的運(yùn)行效果一模一樣,但是程序的運(yùn)行過(guò)程卻有了很大的區(qū)別。通過(guò)本章的學(xué)習(xí),我們已經(jīng)知道了如何對(duì)代碼進(jìn)行重定位,這為我們下一章節(jié)將代碼重定位到DRAM奠定了基礎(chǔ)。


備注:說(shuō)明一下,代碼已上傳到我的資源里,我要了兩個(gè)下載分,不好意思,我的資源分太少了,我得賺點(diǎn),我相信我的程序是絕對(duì)能運(yùn)行的,覺(jué)得值就去下載。

總結(jié)

以上是生活随笔為你收集整理的tiny4412 裸机程序 六、重定位代码到IRAM+0x8000的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。