找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7023|回復(fù): 5
收起左側(cè)

ARM菜鳥成長記

[復(fù)制鏈接]
ID:76190 發(fā)表于 2015-4-5 17:43 | 顯示全部樓層 |閱讀模式
從開始搞ARM到現(xiàn)在將近半年多了,第一個項目搞得有些眉目了,終于感覺像是入門了,半年來,有開始的新鮮,中間的苦悶,到最后的欣喜。其中過程可謂曲折離奇,遇到了很到前人沒有遇到過的疑難雜癥,當(dāng)然很多時候是因為我的粗心釀成的。曾經(jīng)也有過放棄的念頭,那個焦慮,像得了狂躁癥一樣。后來下定決心即使績效沒了,工作丟了也要搞完它。其實在這個過程中,看到跟我一樣的很多新人在論壇上發(fā)帖求助,可是很多時候回者寥寥無幾,可能問題太幼稚,也可能問題描述的不清楚。我發(fā)過很多帖子,甚至直接騷擾了網(wǎng)上很多的牛人,他們都給了我很大的幫助,但是我當(dāng)時的想法太簡單了,總想著某個牛人能夠解決掉這個問題,現(xiàn)在想想,即使是牛人,沒有看到具體的問題也很難給你一個解決方法,遇到困難不能把希望完全寄托在別人身上,要挖掘自身潛力,一遍遍仔細(xì)看手冊,反復(fù)試驗,不斷思考,問題肯定能解決掉,只是時間問題而已。再次要感謝公司對我的容忍,一個這么簡單的東東允許我搞了這么久。

    其實,在前面的過程中,一直有寫點什么的沖動,但是當(dāng)時困難重重、前途未卜,也沒了這個心情,F(xiàn)在可以坐下來仔細(xì)總結(jié)下前面的問題,有現(xiàn)在都沒搞明白的,特向大家請教了;有解決掉的,那就說說經(jīng)驗教訓(xùn),給其他人一些參考。首先聲明本人腦瓜笨,邏輯思維差,點一個燈點了一個多月,最后還發(fā)現(xiàn)沒點對。所以提到的問題可能很幼稚,說話也好像前言不搭后語,有興趣看的那就受累了哈。

    先說說我們的這個塊板子,裸奔的at91sam9260,外擴(kuò)Norflash、SRAM,實現(xiàn)程序既可以跑在Norflash中,也可以拷貝到Sram中跑。任務(wù)就一個:控制一個片外AD,讀出數(shù)據(jù)然后通過串口發(fā)出。很簡單的吧,這我都搞了幾個月呢,你說菜不菜吧。以下我將回想整個的ARM學(xué)習(xí)過程,涉及到的知識都是很簡單的基礎(chǔ)知識,老鳥就不用看了,希望可以幫助到像我一樣的菜鳥。

    前三個月主要是熟悉的過程,當(dāng)時完全沒有想到后面程序的調(diào)試會如此的困難,想當(dāng)然地認(rèn)為又不上系統(tǒng),無非是32位的單片機(jī)嘛。板子做回來一大段時間內(nèi),元器件都沒有湊齊,當(dāng)時傻了呀,應(yīng)該先熟悉熟悉編程環(huán)境,每天就為幾個破元件折騰,什么都沒干。

    后來板子焊接好了,才發(fā)現(xiàn)只會用H-JTAG識別芯片,其他的什么都不懂。然后開始看例程,只玩過51的我,初次接觸32位的單片機(jī),當(dāng)時看到AT91C_BASE_PMC->PMC_PCER=(0x1<<3)這樣的語句,竟然不知道是什么意思,一是困惑->代表個啥?二是為啥寫成0x1<<3的樣子?后來不知過了多久才明白,AT91C_BASE_PMC是個基地址,PMC_PCER是相對這個基地址的偏移,移位賦值是為了給32位寄存器賦值的方便。

先說說開發(fā)ARM要用到的軟件以及工具吧,這段時間我接連使用了IAR、KEIL、h-jtag、JLink,都會用但是都不精通。最后是在KEIL+Jlink下完成的。

開發(fā)工具的選擇:
1、編譯環(huán)境:IAR、KEIL、GCC、……

    開始我想也沒想就選擇了IAR,原因很簡單:ATMEL的例程很都是基于IAR的,而KEIL安裝目錄下的例程很少。匆忙安裝了IAR當(dāng)時的最新版IAR5.20,完全沒有考慮可用的資源和交流的方便。然后才發(fā)現(xiàn)IAR5.X跟4.X有很大的不同,主要就是其中的鏈接器從XLINK換成了ILINK,所以配置文件也由XCL文件換成了ICF文件,初看后者好像比前者更簡單更易懂了,但是由于是新版,使用的人還不多,網(wǎng)上上的參考資料大部分還是基于4.X的,對于新手哪幾條語句還是很費解。

    不過一根筋的我還是硬著頭皮堅持使用IAR5.20,直到遇到IAR的殺招:系統(tǒng)從慢時鐘想快時鐘切換時就跑飛了,都是死在lowlevelinit()中的這一句上:AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLLA_CLK;然后將這一句放在主程序中,照死不誤。使用過程中,總彈出一個警告,大致意思就是說:IAR安裝目錄下,bin文件夾下的armlibsupport.dll may be missing or corrupt.重新裝后還是老樣子。在LED閃爍程序上折騰一個多月未果后,才痛下決心轉(zhuǎn)向KEIL。

   用上KEIL才發(fā)現(xiàn)這玩意不是傳說中的弱智,相反特別適合我等菜鳥,感覺主要有三個方面特別好:啟動代碼的圖形化配置;在Flash跑不需要什么配置文件,直接在option中添兩個地址值就可以了;只需點擊鼠標(biāo)就可以實現(xiàn)將代碼從Flash自動拷貝到RAM中執(zhí)行,不需要再寫什么代碼拷貝程序了。
GCC,沒用過,不懂。

2、調(diào)試工具:JLINK、H-JTAG、ULINK、……
    開始使用h-jtag,配合Wiggler使用,小巧且便宜,不得不佩服Twentyone前輩,在RAM中調(diào)試很方便,也可以通過H-Flasher將程序下載到Flash跑,使用h-flasher時要一個初始化文件,主要是初始化Flash相關(guān)寄存器。
    后來看到DB的JLINK都白菜價了,就從淘寶買了一個JLINK,主要是不用再用并口了,現(xiàn)在百元以內(nèi)的JLINK大把,用JLINK是個不錯的選擇,但是調(diào)試片外的flash好像還不能無限斷點。
ULINK,不太清楚,好像只支持KEIL,不過沒用過。

今天先寫到這里,不好意思,牢騷多于知識了。接下來準(zhǔn)備說說我對REMAP、Bootloader等概念的理解。
第一次搞ARM特別是從51直接跳到ARM的必須面對的幾個概念:REMAP、Bootloader、Flashloader。

1、REMAP:
    提到REMAP。首先應(yīng)想到什么是MAP,英語不好,開始就斷章取義,MAP就是地圖嘛,Memory Map就是存儲器地圖,不過這個地圖的參考坐標(biāo)不是經(jīng)緯度,而是地址,進(jìn)而叫做存儲器映射。由于要適應(yīng)不同存儲器容量要求的用途,ARM處理器本身的RAM、ROM并不是足夠大,所以很多時候要外擴(kuò)一些存儲器,Norflash、NANDFlash、SDRAM、SRAM……而對于ARM來說怎么識別這些不同的存儲器呢,只能給每個分配一個獨立的地址,就相當(dāng)于每個人有不同的名字。片內(nèi)存儲器的地址一般出廠就固化好的,片外的話就根據(jù)每個存儲器所連接的外部總線片選而具有不同的地址。

    所以REMAP,顧名思義就是存儲器的重新映射,即某些存儲器的地址又發(fā)生了變化。我就很不理解了,這地址本來就不好記,還變來變?nèi)サ,麻不麻煩呀,學(xué)51的時候咋就沒這玩意呢?后來查了些資料,有些明白了,51是8位機(jī),更重要的是51的主頻不高,8位的ROM或Flash足夠匹配51的主頻,不用插入等待指令,所以程序直接在ROM或Flash中跑影響不到系統(tǒng)的速度。而ARM就不同了,ARM是32位機(jī),但是Flash一般是8位或16位,32位的也有吧,好像價格很高。而且ARM的制品很高,動輒上百M,所以Flash的工藝達(dá)不到這個速度。如果程序跑在Flash中就要插入過多的等待指令,所以會影響ARM的性能。而RAM一般存取速度比較快,很容易構(gòu)成32位,可以與高速的ARM匹配。更重要的是ARM上電后必須從0x0地址處取得指令,因此上電后必須將ROM或Flash映射位0X0地址處,當(dāng)時還產(chǎn)生了一個弱智的想法,既然RAM這么好,為啥還要ROM或Flash,直接將程序下載到RAM中不就得了,后來才猛地想到RAM是易失型存儲器,掉電后啥也沒了,再上電后0X0處啥都沒有。而且還有一條,ARM的中斷向量表,既存放各個中斷入口地址的地方,一般放在0x0處,即ROM或Flash中,為了加快中斷響應(yīng)速度,也應(yīng)該將0X0映射到RAM中去。因此,ARM一般從ROM或Flash啟動完成初始化,然后將應(yīng)用程序拷貝到RAM,然后跳到RAM執(zhí)行。

    剛才說的是,為啥要REMAP,接下來說怎么REMAP。開始的時候我就不清楚,都說REMAP,那怎么才能完成REMAP呢?都是手冊看得少呀,其實上面說的已經(jīng)很清楚了,我們用的at91sam9260更是簡單,有專門的寄存器可以配置,MATRIX_MRCR—Master Remap Control Register,向這個寄存器相應(yīng)位寫1就可以了。網(wǎng)上還看到Samsung的某些ARM可以通過編程相應(yīng)Bank寄存器改變其起始地址,來實現(xiàn)REMAP。

    下面以我們的at91sam9260的板子為例詳細(xì)說說我對at91sam9260 REMAP的理解,開始Flash沒有任何程序,當(dāng)然也沒有REMAP,此時將BMS接高,然后上電,此時的0X0地址處位于片內(nèi)的ROM,由于ROM內(nèi)好像固化了引導(dǎo)程序,所以此時串口會輸出“Rom Boot…>”字樣。而內(nèi)部的SRAM0的起始地址還是在0x20 0000處,而片外Norflash起始地址是0x1000 0000處。然后我們利用h-flasher或J-Flash將生成的Bin文件下載到Norflash內(nèi),即起始地址為0x1000 0000處。然后將BMS接低,此時Norflash被映射在0X0地址處,即此時Norflash的起始地址為0X0,(你可能要問那ROM的地址現(xiàn)在在哪兒呢?我也不知道,因為Norflash的地址范圍是0X0~0X1F FFFF,而ROM的起始地址默認(rèn)是0X10 0000,恰好在Norflash的范圍內(nèi),所以此時ROM哪兒去了?)此時上電,因為0X0地址處即Norflash起始地址有八個合法的中斷向量,程序會從Norflash啟動,接著執(zhí)行啟動代碼,初始化SMC、PMC,然后Copy中斷向量表到內(nèi)部SRAM0,然后,將MATRIX_MRCR寄存器相應(yīng)位置1,實現(xiàn)REMAP,此時,Norflash的起始地址又變回0X1000 0000,而內(nèi)部的SRAM0的起始地址又變回0x0了,系統(tǒng)如果發(fā)生異常,將從地址0X0處即內(nèi)部SRAM0取中斷向量,而內(nèi)部SRAM的訪問速度顯然高于外部的Norflash,所以提高程序性能。這是我對at91sam9260 REMAP的理解,歡迎討論指教。

2、Bootloader:

    說實話,這個概念到現(xiàn)在也不是很明白。可能對于裸奔的系統(tǒng)來說,Bootloader這個概念本身就比較模糊吧,望文生義的話,Boot,靴子,Load,穿上靴子走路才比較舒服(這個比喻好像比較爛喔),對于ARM來說,初始化好,并將向量表以及數(shù)據(jù)什么的拷貝到RAM,運行起來才順暢。就是傳說中的引導(dǎo)裝載。所以我理解的Bootloader就是完成ARM的初始化、建立中斷向量表并映射到RAM中、將數(shù)據(jù)段和必要的代碼段拷貝到RAM、完成REMAP、跳轉(zhuǎn)到Main,這一系列過程。說白了就是啟動代碼干的活。這個理解我自己都感覺很牽強(qiáng),還請大家多多指點。

3、Flashloader:
    這個概念更是模糊,總感覺跟Bootloader差不多,只不過Flashloader可以實現(xiàn)對Flash的讀寫、擦除等操作,并與調(diào)試軟件配合實現(xiàn)將程序下載到Flash中。IAR中有一個選項:Use Flashloader,不過好像一般都是針對片內(nèi)Flash的,我們的板子是外擴(kuò)的Norflash,好像就沒有用到這個東東。

接下來準(zhǔn)備說說基于KEIL MDK下的啟動代碼的理解。

提起啟動代碼,我就嗷嗷郁悶,IAR下的程序都死在了這里,Keil中出現(xiàn)的問題很多都是通過對啟動代碼的修修補(bǔ)補(bǔ)才解決的,一句話:成也啟動代碼,敗也啟動代碼。

啟動代碼應(yīng)該是剛接觸ARM的新手必須面對而又很頭痛的問題吧,剛開始我也很納悶,為什么搞個這玩意,學(xué)51的時候咋就沒見過呢。而且還都是匯編寫的,俺的匯編還停留在“MOV”階段,其他的不是很懂,沒辦法,誰讓匯編的效率高呢。提到啟動代碼還不得不老生常談一下其中要完成的任務(wù):

1、建立異常中斷向量表,ARM從0X0開始給每個異常中斷分配4個字節(jié)的空間,一般存放一個跳轉(zhuǎn)指令(B)或PC的裝載指令(LDR PC,X_Vector),當(dāng)發(fā)生異常時,ARM從此處取得相應(yīng)異常中斷處理程序入口地址,再跳轉(zhuǎn)執(zhí)行;
2、ARM都是高速處理器,而在高速下啟動很可能會不穩(wěn)定,所以在啟動代碼從慢時鐘開始運行,在適當(dāng)?shù)奈恢,?2.768K切換到高速運行;
3、ARM一般帶有片外存儲器,F(xiàn)lash、SDRAM等,這些存儲器都需要初始化才能使用,這都是在啟動代碼中完成,但是Norflash的初始化要在時鐘初始化之前;
4、ARM有不同的模式,每種模式都需要相應(yīng)的堆棧;
5、Copy異常中斷向量表到RAM,并實現(xiàn)REMAP,具體請參照上一節(jié);
6、Copy可執(zhí)行映像的數(shù)據(jù)段到RAM,并將ZI區(qū)清零。這個一般都是由編譯器完成的,IAR下是?main來實現(xiàn),Keil中由__main實現(xiàn)。
現(xiàn)在啟動代碼可以看懂一些,不過自己寫啟動代碼還是很遙遠(yuǎn)的事情。如果開始對啟動代碼很抵觸,可以考慮使用Keil,因為Keil由啟動代碼的圖形化配置,直接點擊鼠標(biāo)操作就可以實現(xiàn)自己的啟動代碼。下面結(jié)合我們at91sam9260的板子,說說Keil中的啟動代碼。

打開Keil生成的SAM9260.S,點擊左下角的“Configuration Wizard”進(jìn)入圖形化配置向?qū),根?jù)你的需要選擇參數(shù),全部選擇完畢后,再點擊"Text Editor",將會看到生成的啟動代碼。
我靠,不是吧,將近2000行,開始你可能會很泄氣,但仔細(xì)一看,前面不都是些宏定義嘛,跟圖形化配置向?qū)б灰粚?yīng)的,只有從1200多行的這一句開始的才是真正的啟動代碼部分。
;----------------------- CODE --------------------------------------------------

                PRESERVE8  
開始是8個PC裝載指令,注意第六個向量,即地址0X14處,存放可執(zhí)行映像的大小,||Image$$ER_ROM1$$RO$$Length||+||Image$$RW_RAM1$$RW$$Length||
。
接下來是SMC、PMC的初始化,我們的板子外擴(kuò)了Norflash,如果在未初始化Norflash前,切換到快時鐘,系統(tǒng)起不來,所以應(yīng)該先初始化SMC,再初始化PMC,而Keil自帶的啟動代碼中默認(rèn)PMC在前,怎么辦,可以將前面PMC的宏定義部分和初始化部分剪切,然后分別粘貼在SMC宏定義部分和初始化部分的后面,然后再看“Configuration Wizard”中,PMC自動放到了SMC的后面了。
接下來是關(guān)閉看門狗(默認(rèn)是打開的),拷貝異常中斷表到RAM中,然后REMAP,建立緩存,建立各個模式的堆棧指針。
最后進(jìn)入__main進(jìn)行數(shù)據(jù)段和代碼段的拷貝以及初始化C語言庫函數(shù),然后跳轉(zhuǎn)到main執(zhí)行。

Keil中有詳細(xì)的注釋,理解起來應(yīng)該不是很難,具體的語句無需明白,知道個大致意思就行了。無非是將某個外設(shè)的基地址裝載(LDR)到一個寄存器R0,將要向這個外設(shè)的某個寄存器賦的值裝載到另一個寄存器R1,然后加載(STR)。一般的模式就是這樣:
LDR   R0,=Periphral_BASE     ;某外設(shè)的基地址
LDR   R1,=0XFFFF0000         ;向寄存器要賦的值
STR    R1,[R0,#Periphral_Register_OFS] ;向外設(shè)Peripheral基地址偏移OFS的寄存器Register賦值0xFFFF0000

Keil的啟動代碼部分有兩個注意的地方:
1、啟動代碼中有很多IF語句,如:IF      :DEF:RAM_INTVEC。這就可以通過在Options/Asm對話框中的Define中填入RAM_INTVEC就可以實現(xiàn)中斷向量從Flash到RAM的拷貝。同理,還有IF      :DEF:REMAP等等;
2、帶有Keil特色的MICROLIB,通過在Options/Target中選擇“Used MICROLIB”,比不使用微庫相比生成的代碼較小。不過除此之外,應(yīng)該還有其他的關(guān)系,因為我們的程序如果選擇不使用微庫的話,就執(zhí)行不成功。對于微庫只有這些很片面的理解,還請老手指教。

總而言之,Keil中的啟動代碼還是比較好理解的,而且借助圖形化配置向?qū),可以更快的上手,以實現(xiàn)自己的啟動代碼。

下面要說說Keil下,怎樣實現(xiàn)程序在片外Norflash運行、片外SRAM調(diào)試、片外SRAM運行。



回復(fù)

使用道具 舉報

ID:78487 發(fā)表于 2015-4-29 22:34 | 顯示全部樓層
很好的經(jīng)歷,,我還是學(xué)生黨一名,好好學(xué)學(xué)
回復(fù)

使用道具 舉報

ID:548519 發(fā)表于 2019-6-10 23:50 | 顯示全部樓層
我也是arm的菜鳥,新手,無論如何都要堅持下去,學(xué)習(xí)了,感謝!
回復(fù)

使用道具 舉報

ID:445069 發(fā)表于 2019-7-18 20:23 | 顯示全部樓層
ARM菜鳥一名,開始向ARM邁進(jìn)。
回復(fù)

使用道具 舉報

ID:591572 發(fā)表于 2019-7-28 11:13 | 顯示全部樓層
我也是 新手  還是有些看不懂嗷
回復(fù)

使用道具 舉報

ID:216959 發(fā)表于 2019-8-21 09:45 | 顯示全部樓層
新手一個,正在學(xué)習(xí)
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表