新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM開發(fā)過程中最最需要注意的問題

ARM開發(fā)過程中最最需要注意的問題

作者: 時(shí)間:2016-11-11 來源:網(wǎng)絡(luò) 收藏
平時(shí)大家接觸最多的可能是X86平臺(tái),在這種系統(tǒng)上寫程序幾乎不需要考慮太多問題,但ARM上就不一樣了,最常見也最容易被忽略的問題可能就是字節(jié)的對(duì)齊,即使像我這樣有六七年程序開發(fā)經(jīng)驗(yàn)的才手也時(shí)常難于提防,最近就有一個(gè)BUG,花了一天時(shí)間最終發(fā)現(xiàn)是對(duì)齊引發(fā)的,在此與大家分享,但愿大家能夠注意到。

  我在EBOOT中讀取存在HARD DISK上的nk.bin文件,從而從HARD DISK上LOAD WINCE系統(tǒng),在這個(gè)過程中總是有check sum錯(cuò)誤,但從ethernet下載時(shí)不會(huì)有錯(cuò),所以問題應(yīng)該還是在我加的這部分代碼上,而且同樣的代碼在PC上能正常運(yùn)行。經(jīng)過檢查代碼的邏輯關(guān)系是正確的。接著我在出錯(cuò)時(shí)將那些數(shù)據(jù)全部用調(diào)試信息打出來,發(fā)現(xiàn)從文件開始算起第4096個(gè)字節(jié)被丟掉了,而其它的字節(jié)都是對(duì)的。初步判斷是對(duì)齊引發(fā)的問題,所以去查每一個(gè)BUFFER,最終發(fā)現(xiàn)是在讀取硬盤數(shù)據(jù)時(shí)BUFFERR并沒有按雙字節(jié)對(duì)齊,而硬盤以16BIT讀取數(shù)據(jù),而引發(fā)了錯(cuò)誤。

實(shí)際上,這類問題在ARM系統(tǒng)上很常見,讓人防不勝防,以下是我的一些例子。

1,解析數(shù)據(jù)流時(shí)應(yīng)該時(shí)刻注意。如果需要把一個(gè)數(shù)據(jù)流(BUFFER)轉(zhuǎn)化成結(jié)構(gòu)進(jìn)行取值,就應(yīng)該把這個(gè)結(jié)構(gòu)定義為按字節(jié)存取.考慮如下結(jié)構(gòu):

struct a{

char a;
short b;
long c;
};
如果某個(gè)數(shù)據(jù)流中包含這樣的結(jié)構(gòu),而且我們要直接將數(shù)據(jù)流的指針轉(zhuǎn)化成該結(jié)構(gòu)的指針,然后直接取結(jié)構(gòu)成員的值,我們就應(yīng)該將這個(gè)結(jié)構(gòu)定義成按字節(jié)訪問,即將其夾在語句
#pragma pack(push,1)
...

#pragma pack(pop)
之中。如果我們不這樣做,編譯器會(huì)將成員b的地址對(duì)齊到short指針的地址,即在a之后加上一個(gè)char即8位的成員,將C對(duì)齊到LONG,即在B之后再加一個(gè)char成員。如此一來,成員B和成員C就得不到正確的值了。

如果我們定義一個(gè)普通的結(jié)構(gòu)用來存放一些數(shù)據(jù),則不用定義成按字節(jié)存取,編譯器會(huì)加上一些占位成員,但并不會(huì)影響程序的運(yùn)行。從這個(gè)意義上講,在ARM中,將結(jié)構(gòu)成員定義成CHAR和SHORT來節(jié)約內(nèi)存是沒有意義的。

一個(gè)典型的例子就文件系統(tǒng)的驅(qū)動(dòng)程序,文件是以一些已經(jīng)定義好的結(jié)構(gòu)存放在存儲(chǔ)介質(zhì)上的,它們被讀取到一個(gè)BUFFER中,而具體取某個(gè)文件、目錄結(jié)構(gòu)時(shí),我們會(huì)將地址轉(zhuǎn)化成結(jié)構(gòu)而讀取其中的值。


2,訪問外設(shè)時(shí)。
例如,磁盤驅(qū)動(dòng)通常以16BIT的方式存取數(shù)據(jù),即每次存取兩個(gè)字節(jié),這樣就要求傳給它的BUFFER是雙字節(jié)對(duì)齊的,驅(qū)動(dòng)程序應(yīng)該至上層傳來的指針做出正確的處理以保證數(shù)據(jù)的正確性。


3.有時(shí),我們沒有將數(shù)據(jù)流指針轉(zhuǎn)化為結(jié)構(gòu)指針取值,但如果我們讀取的是雙字節(jié)或者是四字節(jié)的數(shù)據(jù),同樣需要注意對(duì)齊的問題,例如,如果從一個(gè)BUFFER的偏移10處讀取一個(gè)四字節(jié)值,則實(shí)際得到的值是偏移8處的
地址上的DWORD值。
如何改wince裝驅(qū)動(dòng)
前邊說了如何在開發(fā)版上裝wince.現(xiàn)在我手上有一個(gè)usb的攝像頭,為了要他能在開發(fā)板上使用,我得給他裝上驅(qū)動(dòng).產(chǎn)家提供了dll和需要修改注冊(cè)表的說明.下邊說下步驟,

打開之前做wince內(nèi)核定制燒寫的工程,把驅(qū)動(dòng)文件,假設(shè)叫A.dll, 拷貝到工程目錄下,D:WINCE420PUBLICwince工程RelDirSAMSUNG_SMDK2410_ARMV4Release 這個(gè)下邊.然后在pb工作環(huán)境中,找到ParameterView區(qū),展開樹型列表,找到project.bib和project.reg兩個(gè)文件,要對(duì)他們進(jìn)行修改.

本文引用地址:http://m.butianyuan.cn/article/201611/316596.htm

修改 project.bib 添加 A.dll $(_FLATRELEASEDIR)A.dll NK SH 這樣一行 .

將產(chǎn)家提供的reg文件里的內(nèi)容copy到project.reg里.

以上做好后,因?yàn)槲沂莗b4.2的環(huán)境,這時(shí)候點(diǎn)bulide菜單下的make image.等完成后,再重新燒寫一遍鏡像文件(nk) 到開發(fā)板上就可以了。注意我這里選make image而不是build platform。如果選build platform會(huì)抱錯(cuò)的,說找不到dll等等幾個(gè)錯(cuò)誤。我買的周立功的一本書上是在pb5.0環(huán)境下,到這一步時(shí)說 在菜單buuild os中,不選clean before building。然后再選擇sysgen重新編譯生成新的wince映像

物理地址映射方法分為兩種,一種靜態(tài)映射另一種為動(dòng)態(tài)映射。在OEMAddressTable中定義了物理地址與虛擬地址的映射關(guān)系屬于靜態(tài)映射,用VirtualCopy映射屬于動(dòng)態(tài)映射,采用哪種辦法都可以。問題中提到的屬于靜態(tài)映射,2440的BSP在map.a文件中定義了IIC控制寄存器的物理起始地址和對(duì)應(yīng)的虛擬地址如下:
DCD 0x91400000, 0x54000000, 1 ;
在OEMAddressTable中定義的虛擬地址范圍在0x8000 0000—0x9FFF FFFF,這部分可緩存,適合內(nèi)核程序和應(yīng)用程序使用,同時(shí)WINCE內(nèi)核在0xA000 0000—0xBFFF FFFF中映射了另一份,指向了同樣的物理地址,這部分不可緩存,適合驅(qū)動(dòng)程序使用。三星ARM處理器帶有L1級(jí)高速緩存,可緩存會(huì)提高執(zhí)行效率。對(duì)于特殊的設(shè)備寄存器適合映射到不可緩存的虛擬地址。
當(dāng)驅(qū)動(dòng)程序調(diào)用VirtualCopy對(duì)0xB1400000地址讀寫時(shí),WINCE自動(dòng)將這個(gè)地址減去0x2000 0000,也就是0x91400000,對(duì)應(yīng)的物理地址就是0x54000000,也就是IIC控制寄存器的物理起始地址。




關(guān)鍵詞: ARM開發(fā)過

評(píng)論


技術(shù)專區(qū)

關(guān)閉