標(biāo)題:
寫在“五一”之解析IAR的ILINK鏈接器icf配置文件
[打印本頁(yè)]
作者:
xuwei
時(shí)間:
2015-6-24 17:05
標(biāo)題:
寫在“五一”之解析IAR的ILINK鏈接器icf配置文件
五一來(lái)了,三天小假期終于可以讓大家歇一歇了(估計(jì)好多人都已經(jīng)在規(guī)劃著五一出行計(jì)劃了或者已經(jīng)在旅途中了),校園里一下子冷清了不少。記得去年12月份曾經(jīng)寫過(guò)一篇“寫在圣誕節(jié)之簡(jiǎn)單破解飛思卡爾HCS12系列Flash空間限制“的文章,當(dāng)時(shí)還頗受歡迎來(lái),至今仍保持著我博客的點(diǎn)擊記錄,哈哈,所以今天再續(xù)寫一篇"五一特別篇"(嘿嘿,最近看海賊王看的,也出個(gè)特別篇,哈哈,豐富下俺博客的藝術(shù)形式),希望不要石沉大海的好。
勞動(dòng)節(jié)嘛,自然勞動(dòng)最光榮,呵呵,所以我還是變回技術(shù)宅,鉆進(jìn)實(shí)驗(yàn)室搗鼓下技術(shù)吧,順便寫寫心得體會(huì)、工程經(jīng)驗(yàn)之類的給大家分享分享(所以勞動(dòng)人民是最美麗滴啊,呼呼)。這里首先得說(shuō)聲抱歉了,好像月初有網(wǎng)友要求寫篇有關(guān)kinetis的DMA功能的介紹,也答應(yīng)了盡量本月份就寫出來(lái),不過(guò)主要是更新從零入手系列很麻煩,每寫一篇的時(shí)候我都需要仔細(xì)斟酌,保證質(zhì)量(畢竟不能砸了招牌嘛,嘿嘿),而且本月也的確有些忙,所以這個(gè)月底就不更新了,下個(gè)月會(huì)更新出來(lái),敬請(qǐng)期待哦,哈哈。
本篇介紹介紹IAR的icf配置文件,其實(shí)這算是一篇知識(shí)深入擴(kuò)展,初手在用IAR簡(jiǎn)單開發(fā)一款片子的時(shí)候很少有人去關(guān)心該配置文件的,因?yàn)樵撆渲梦募话阍谟肐AR新建工程選型目標(biāo)芯片的時(shí)候系統(tǒng)自動(dòng)添加了(當(dāng)然kinetis的官方例程里給出的配套的配置文件需要另行自己添加了),會(huì)覺得這是IDE系統(tǒng)的事。但是如果你是要做深入研究或者說(shuō)真正掌握了解一款片子,而不是霧里看花知其然而不知其所以然,那么配置文件則是你的必修內(nèi)容,怎么樣,好奇了吧,呵呵,下面深入了解一番吧,進(jìn)入正題:
1.首先說(shuō)說(shuō)什么是icf文件(即ILINK鏈接器的配置文件)的作用,其實(shí)在IAR5.x之前,IAR是采用的叫XLINK的鏈接器(它相應(yīng)的配置文件為xcl文件),5.x之后才采用了新版ILINK鏈接器,所以咱們開發(fā)Kinetis的IAR6.x自然也采用的是ILINK鏈接器,配置文件為icf文件,咳咳,如果有人問(wèn)什么是鏈接器,先谷歌一下補(bǔ)補(bǔ),我這里就引用IAR官方手冊(cè)里的一句話簡(jiǎn)要說(shuō)明一下什么是鏈接器及其相應(yīng)配置文件的作用吧:
”EWARM 5.xx 中的鏈接器稱為ILINK。ILINK 可以從 ELF/DWARF 格式的目標(biāo)文件中提取代碼和數(shù)據(jù), 并生成可執(zhí)行的輸出鏡像。對(duì)于 ELF/DWARF 格式而言,基本的鏈接單元是section,section 的類型有code和data,屬性可以是readonly (ro),readwrite (rw)和zeroinit (zi)。ILINK 根據(jù) ILINK Configuration File(*.icf)來(lái)分配和定位這些sections!
2.簡(jiǎn)單的概括icf的文件,其主要包括以下幾個(gè)內(nèi)容,即:
(1)可編址的存儲(chǔ)空間(memory);
(2)不同的存儲(chǔ)地址區(qū)域(region);
(3)不同的地址塊(block);
(4)section的初始化與否;
(5)section在存儲(chǔ)空間的放置
。
上面幾點(diǎn)內(nèi)容,如果你對(duì)照實(shí)際icf文件都會(huì)找得到,建議大家嘗試下,會(huì)讓你受益匪淺的。
3.對(duì)于icf文件使用的常用命令,在網(wǎng)上早已有人貼出來(lái)了,隨意即可搜到,這里省去麻煩,我也貼出來(lái)自己學(xué)的時(shí)候記下來(lái)的命令用法,建議通讀一遍:
(1)define [ exported ] symbol name = expr;
作用:指定某個(gè)符號(hào)的值。
參數(shù):
exported 導(dǎo)出該symbol,使其對(duì)可執(zhí)行鏡像可用
name 符號(hào)名
expr 符號(hào)值
舉例:
define symbol RAM_START_ADDRESS = 0x40000000; /* 定義 RAM 起始地址 */
define symbol RAM_END_ADDRESS = 0x4000FFFF; /* 定義 RAM 結(jié)束地址 */
-------------------------------------------------------------------
(2)define memory name with size = expr [, unit-size];
作用:
定義一個(gè)可編址的存儲(chǔ)地址空間(memory)。
參數(shù):
name memory的名稱
expr 地址空間的大小
unit-size expr的單位,可以是位(unitbitsize),缺省是字節(jié)(unitbytesize)
舉例:
define memory MEM with size = 4G;
-----------------------------------------------------------------
(3)define region name = region-expr;
作用:
定義一個(gè)存儲(chǔ)地址區(qū)域(region)。一個(gè)區(qū)域可由一個(gè)或多個(gè)范圍組成,每個(gè)范圍內(nèi)地址必須連續(xù),但幾個(gè)范圍之間不必是連續(xù)的。
參數(shù):
name region的名稱
region-expr memory:[from expr { to expr | size expr}],可以定義起止范圍,也可以定義起始地址和region的大小
舉例:
define region ROM = MEM:[from 0x0 size 0x10000];
/* 定義 ROM region,位于地址空間MEM 中,起始地址為0x0,大小為0x10000 字節(jié) */
define region ROM = MEM:[from 0x0 to 0xFFFF];
/* 定義 ROM region,位于地址空間MEM 中,起始地址為0x0,結(jié)束地址為0xFFFF */
---------------------------------------------------------------------------------------------
(4)
define block name [ with param, param... ]
{
extended-selectors
};
作用: 定義一個(gè)地址塊(block);它可以是個(gè)只保留指定大小的地址空間的空塊,比如棧、堆;也可以包含一系列的sections,由extended-selectors 選擇。
參數(shù):
name block 的名稱
param 可以是: size = expr (塊的大小)
maximum size = expr (塊大小的上限)
alignment = expr (最小對(duì)齊字節(jié)數(shù))
fixed order (按照固定順序放置sections)
extended-selector [ first | last ] { section-selector | block name | overlay name }
first 最先存放
last 最后存放
section-selector [ section-attribute ][ section sectionname ][object filename ]
section-attribute [ readonly [ code | data ] | readwrite [ code | data ] | zeroinit ]
sectionname section的名稱
filename 目標(biāo)文件的名稱
name block或overlay的名稱
注:這里可以按照section的屬性,名稱及其所在目標(biāo)文件這三個(gè)過(guò)濾條件中,任意選取一個(gè)條件或多個(gè)條件進(jìn)行組合,來(lái)圈定所要求的sections。
舉例:
define block HEAP with size = 0x1000, alignment = 4 { };
/* 定義 HEAP block,大小為0x1000,4 字節(jié)對(duì)齊,沒(méi)有內(nèi)容 */
define block MYBLOCK1 = { section mysection1, section mysection2, readwrite };
/* 定義 MYBLOCK1 block,含有mysection1,mysection2,以及所有readwrite 屬性的sections */
define block MYBLOCK2 = { readwrite object myfile2.o };
/* 定義 MYBLOCK2 block,含有目標(biāo)文件myfile2.o 中所有readwrite 屬性的sections */
define block MYBLOCK3 = { readonly code object myfile3.o };
/* 定義 MYBLOCK3 block,含有目標(biāo)文件myfile3.o 中所有readonly 屬性的code sections */
(5)
initialize { by copy | manually } [ with param, param... ]
{
section-selectors
};
作用: 初始化sections
參數(shù):
by copy 在程序啟動(dòng)時(shí)自動(dòng)執(zhí)行初始化
manually 在程序啟動(dòng)時(shí)不自動(dòng)執(zhí)行初始化
param 可以是: packing = { none | compress1 | compress2 | auto } copy routine = functionname
packing表示是否壓縮數(shù)據(jù),缺省是auto
functionname表示是否使用自己的拷貝函數(shù)來(lái)取代缺省的拷貝函數(shù)
section-selector 同上
舉例:
initialize by copy { readwrite }; /* 在啟動(dòng)時(shí)初始化所有屬性為 readwrite 的sections */
--------------------------------------------------------------
(6)
do not initialize
{
section-selectors
};
作用: 規(guī)定在程序啟動(dòng)時(shí)不需要初始化的sections;一般用于__no_init 聲明的變量段(.noinit)
參數(shù):
section-selector 同上
舉例:
do not initialize { .noinit }; /* 在啟動(dòng)時(shí)不要初始化.noinit section */
(7)
place at { address memory [:expr] | start of region_expr | end of region_expr }
{
extended-selectors
};
作用: 把section 或 block 放置在某個(gè)具體的起始地址處,或者一個(gè) region 的開始或結(jié)束處
參數(shù):
memory memory 的名稱
expr 地址值,該地址必須在 memory 所定義的范圍內(nèi)
region_expr region 的名稱
extended-selector 同上
舉例:
place at end of ROM { section .checksum }; /* 把.checksum 放在 ROM region 的最后 */
place at address MEM:0x0 { section .intvec }; /* 把.intvec 放在地址 0x0 */
place at address MEM:0x1000 { section .text object myfile.o }; /* the .text section of myfile.o */
place at address MEM:0x1000 { readonly object myfile.o }; /* all read-only sections of myfile.o */
place at address MEM:0x1000 { readonly data object myfile.o }; /* all read-only data sections of myfile.o */
(8)
place in region-expr
{
extended-selectors
};
作用: 把section 或 block (按任意順序)放置在某個(gè)region 中
參數(shù):
region-expr region 的名稱
extended-selector 同上
舉例:
place in ROM { readonly }; /* all readonly sections */
place in RAM { readwrite }; /* all readwrite sections */
place in RAM { block HEAP, block CSTACK, block IRQ_STACK }; /* heap and stacks */
place in ROM { section .text object myfile.o }; /* the .text section of myfile.o */
place in ROM { readonly object myfile.o }; /* all read-only sections of myfile.o */
place in ROM { readonly data object myfile.o }; /* all read-only data sections myfile.o */
下面為系統(tǒng)預(yù)定義(即你是找不到其定義的,所以不要浪費(fèi)時(shí)間去找了,呵呵)的section和block描述,上圖:
4.相關(guān)命令知曉了,也就是大好基礎(chǔ)了,下面就俺就根據(jù)上面?zhèn)的指令獨(dú)家解析下飛思卡爾提供的Kinetis例程包里自帶的icf配置文件,以512KB_Pflash.icf為例介紹一下(當(dāng)初自己上傳的開發(fā)框架代碼里沒(méi)有作相關(guān)注釋,這里就算是補(bǔ)充了吧,哈哈):
(1)首先找到該文件,打開(咳咳,雖然這步算是廢話,不過(guò)為了嚴(yán)謹(jǐn),還是不能少的,呵呵),采用從上到下的順序解讀;
(2)
先定義了一些可讀性的符號(hào),包括異常向量表的起始地址,ROM、RAM 的起止地址和堆、棧的大小等(該地址分配我們可以在Kinetis的datasheet里找到),以前綴__ICFEDIT_開頭的符號(hào)是由圖形化編輯工具 ICF Editor自動(dòng)定義的,可能會(huì)有些人不懂,其實(shí)上面部分代碼是體現(xiàn)在IAR的Options->Linker選項(xiàng)里的(自己去探索一下即可發(fā)現(xiàn))。
(3)
這部分仍然是定義一些符號(hào),由Kinetis的內(nèi)存映射可以知道,其實(shí)其內(nèi)部是由兩部分RAM塊組成的,所以第一步出現(xiàn)RAM_start這一步出現(xiàn)了RAM2_start,另外也定義了中斷向量表在ROM中的地址和在RAM中的地址。code_start定義為0x00000410是緊鄰前面向量表的,也就是說(shuō)向量表占用了0x00000410大小的空間。
(4)
到了這一步就設(shè)計(jì)到具體操作內(nèi)容了,32位地址總線選址4G空間,然后定義了kinetis(512k型號(hào)的哈)的ROM區(qū)的地址范圍和RAM區(qū)(含RAM1和RAM2)的地址范圍。接著下面定義了堆和棧的屬性,8字節(jié)對(duì)齊方式,大小為前面定義的大小即分別為0x1000和0x200。
(5)
對(duì)屬性為readwrite的sections,.data和.textrw的sections不自動(dòng)初始化,對(duì).noinit屬性的sections(即用__no_init修飾的全局和靜態(tài)變量),定義重定位代碼區(qū)為.textrw_init,定義重定位RAM區(qū)為.textrw。
(6)
對(duì)所有的sections 和 blocks 在地址空間中所處的位置進(jìn)行了配置。首先將只讀的異常向量表.intvec放置在_intvec_start地址處(前面已定義),然后將余下的只讀sections以任意順序存放在ROM_region中,將可讀寫的sections和棧、堆這些blocks以任意順序存放在RAM_region中。
呼呼,今晚工作量有點(diǎn)大,沒(méi)想到一寫就寫了這么多,哈哈,終于又找到”文思泉涌“的趕腳了。自己該收收工了,規(guī)劃下這個(gè)五一該怎么玩了,大好時(shí)光不能浪費(fèi)了,大家五一快樂(lè),呵呵。未完待續(xù)~
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1