完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>
標(biāo)簽 > AT91RM9200
AT91RM9200-QU是一種微處理器,數(shù)據(jù)總線寬度是32 bit,而本專題詳細(xì)記載了AT91RM9200開發(fā)調(diào)試手記,并且在設(shè)計(jì)路徑、電路結(jié)構(gòu)設(shè)計(jì)等都有詳細(xì)的說明,對(duì)工程師開發(fā)AT91RM9200設(shè)計(jì)有很大的幫助。
自己的AT91RM9200的板子已經(jīng)調(diào)試了一段時(shí)間了,從開始動(dòng)手制作PCB到現(xiàn)在,差不多有半年的時(shí)間了。在這期間一直忙著查資料,畫板布線,聯(lián)系制板廠家,聯(lián)系購(gòu)買器件(呵呵,大小活全包),一直沒有時(shí)間寫寫總結(jié)之類的東西,另外平時(shí)也沒有養(yǎng)成隨時(shí)總結(jié)的好習(xí)慣。以前搞硬件基本上是以8位的51單片機(jī)為主,偶爾也用用PC104,AVR之類的控制器,其他16位、32位的控制器從沒用過,對(duì)其感覺甚為神秘。因此在做這塊板子之前,自己查閱了很多資料(網(wǎng)上資料為主,資源豐富,比較方便),在做了各種權(quán)衡利弊之后(做方案,選芯片是比較令人頭疼的事情,有過系統(tǒng)設(shè)計(jì)經(jīng)歷的朋友可能有這種體會(huì)),最后才痛下決心,決定選用atmel的AT91RM9200做為控制芯片。因?yàn)樵诖酥皬膩頉]有搞過32位的東東,所以當(dāng)時(shí)心里一點(diǎn)底都沒有。
AT91RM9200-QU是一種微處理器,數(shù)據(jù)總線寬度是32 bit。
基本信息
程序存儲(chǔ)器類型: ROM
程序存儲(chǔ)器大?。?128 KB
數(shù)據(jù) RAM 大?。?16 KB
接口類型: EBI or MCI or MII or SPI or TWI
最大時(shí)鐘頻率: 180 MHz
可編程輸入/輸出端數(shù)量: 122
定時(shí)器數(shù)量: 6
工作電源電壓: 3 V ~ 3.6 V
工作溫度: -40°C ~ 85°C
封裝: PQFP-208
AT91RM9200開發(fā)調(diào)試手記
自己的AT91RM9200的板子已經(jīng)調(diào)試了一段時(shí)間了,從開始動(dòng)手制作PCB到現(xiàn)在,差不多有半年的時(shí)間了。在這期間一直忙著查資料,畫板布線,聯(lián)系制板廠家,聯(lián)系購(gòu)買器件(呵呵,大小活全包),一直沒有時(shí)間寫寫總結(jié)之類的東西,另外平時(shí)也沒有養(yǎng)成隨時(shí)總結(jié)的好習(xí)慣。以前搞硬件基本上是以8位的51單片機(jī)為主,偶爾也用用PC104,AVR之類的控制器,其他16位、32位的控制器從沒用過,對(duì)其感覺甚為神秘。因此在做這塊板子之前,自己查閱了很多資料(網(wǎng)上資料為主,資源豐富,比較方便),在做了各種權(quán)衡利弊之后(做方案,選芯片是比較令人頭疼的事情,有過系統(tǒng)設(shè)計(jì)經(jīng)歷的朋友可能有這種體會(huì)),最后才痛下決心,決定選用atmel的AT91RM9200做為控制芯片。因?yàn)樵诖酥皬膩頉]有搞過32位的東東,所以當(dāng)時(shí)心里一點(diǎn)底都沒有。
1. 制訂方案
選定AT91RM9200之后,接下來就是圍繞它設(shè)計(jì)外圍電路了。因?yàn)槲易龅倪@個(gè)東西應(yīng)用場(chǎng)合比較特殊:野外應(yīng)用,因此在設(shè)計(jì)方案的時(shí)候盡量選用工業(yè)級(jí)的芯片。第一次用這款控制器,設(shè)計(jì)電路的時(shí)候最好的參考就是由atmel官方提供的開發(fā)板:AT91RM9200DK。但是這塊板上的網(wǎng)絡(luò)PHY部分采用的是DM9161E,查資料發(fā)現(xiàn)這個(gè)PHY非工業(yè)級(jí)產(chǎn)品,后來決定把它換成intel的LXT971A。另外我的應(yīng)用中還需要一個(gè)網(wǎng)絡(luò)接口,在非PCI接口的網(wǎng)絡(luò)控制芯片中選來選去,最后決定用SMSC公司的LAN91C111I-NE,也是一款工業(yè)級(jí)別的芯片(網(wǎng)上資料反映其功耗較大,power hungry,但其他工業(yè)級(jí)的片子當(dāng)時(shí)沒有查到,繆辦法呀)。其他的電路基本上都是參考AT91RM9200DK的原理圖設(shè)計(jì)的,除了復(fù)位電路采用了阻容電路(開發(fā)板上那個(gè)復(fù)位芯片國(guó)內(nèi)很難買得到)。
2. 畫圖制板
方案確定之后接下來就是畫原理圖,布線,制板了。之前一直都用protel,在網(wǎng)上查閱資料的時(shí)候發(fā)現(xiàn)了有關(guān)allegro和mentor公司的相關(guān)產(chǎn)品,當(dāng)時(shí)聽說是比較牛的軟件,比protel強(qiáng)多了,當(dāng)時(shí)就有了放棄protel的想法(先不說功能,光是速度就讓我很郁悶,可能是因?yàn)橐郧暗臋C(jī)器比較破的關(guān)系吧)。那學(xué)什么新軟件呢?當(dāng)時(shí)在一個(gè)ftp上發(fā)現(xiàn)了allegro以及相關(guān)的一本書(臺(tái)灣出的那本),而mentor的沒找到多少相關(guān)資料。OK,就allegro了。全新的開始。
因?yàn)橛昧薬llegro的原因,從畫原理圖到最后畫完P(guān)CB,前后將近2個(gè)月的時(shí)間。有關(guān)allegro的應(yīng)用,以后有時(shí)間再寫個(gè)總結(jié)吧,我當(dāng)時(shí)也是現(xiàn)學(xué)現(xiàn)賣。PCB畫完之后,因?yàn)橹瓢骞に嚨脑颍H費(fèi)一般周折之后才把板子交出去(拿到深圳做的,很羨慕在深圳工作的朋友,買器件制板都很方便)。一周之后,終于拿到了樣板。做工看上去蠻不錯(cuò),比在本地做的強(qiáng)多了。
3.焊接檢查
板子做完了,器件也買好了,下面就要焊接調(diào)試了。當(dāng)時(shí)心里是比較緊張的,因?yàn)槲易龅腜CB是雙面板,當(dāng)時(shí)網(wǎng)上有朋友告訴我說雙面板可能會(huì)不穩(wěn)定(9200能跑到200MHz),另外對(duì)自己的布線水平也沒信心(我對(duì)自己的定位是:啥都會(huì),啥都不精)。板子上除了一個(gè)按鍵和幾個(gè)接插件,全部都是表貼。本地有專門提供焊接服務(wù)的,找到他們之后,2個(gè)小時(shí)半塊板子搞定(為什么是半塊?因?yàn)橛幸徊糠旨]有買齊,就是那個(gè)LAN91C111I-NE)。板子焊接完之后拿回來,在上電測(cè)試之前,按照我以前的習(xí)慣,先用萬用表量了一下板子的電源和地。這一量不要緊,驚出我一身冷汗:短路!心情一下子就#??!#@!#@!,怎么搞的嘛!沒別的辦法,檢查吧。首先確定是不是焊接的原因?qū)е碌?,樣板一共做?0塊,拿另外一塊空板量了一下,暈倒!也是短路!
板子上到處是電源和地,怎么檢查呢?我心里知道這種錯(cuò)誤最難檢查了,要命的是我的板子已經(jīng)焊接好了,要是萬一短路的地方在表貼件的下面,那豈不是太殘酷了?我心里一邊暗自禱告,一邊找來一塊板做我的犧牲品,各位可能知道我下一步要做什么了,嘿嘿,從電源輸入的地方開始,逐條把分支割斷。一共割了6刀,終于找到了短路的地方(其中有一處是憑俺肉眼瞅出來的)。短路原因是鋪的銅跟電源線太近而短路(這其中有加工方面的因素,另一方面也是因?yàn)槲以O(shè)置的間距太小了,0.3mm,以后還是用1mm好了)。又在焊接好的板子上割了兩刀,萬用表一測(cè),OK!這次是運(yùn)氣好,以后在焊接之前可要好好測(cè)試板子有沒有問題了。
上面的短路故障是因?yàn)榧庸さ脑驅(qū)е碌?。后來又焊接了一塊板,也出現(xiàn)了短路的問題,是復(fù)位線和地線短路,與上面不同的是,這次短路是因?yàn)楹附訉?dǎo)致的。所以在焊接前后一定要檢查。這兩次都算我運(yùn)氣好,沒有出現(xiàn)燒毀芯片的問題。雖然是比較低級(jí)的錯(cuò)誤,但有時(shí)卻是致命的。
4.初步調(diào)試
確定板子沒有問題之后(至少自己感覺是這樣),下一步就是檢查板子工作是否正常了。根據(jù)手頭掌握的資料,9200從片內(nèi)啟動(dòng)之后,會(huì)通過DEBGUG串口向外發(fā)送‘CCCCC‘字符(至于這個(gè)C字符代表什么含義,接下來會(huì)有描述)。OK,先從這里入手。首先啟動(dòng)超級(jí)終端,參數(shù)設(shè)置為115200,8,no,1,no;
將調(diào)試串口連到PC串口,給板子上電。
超級(jí)終端無反應(yīng),按復(fù)位鍵,濤聲依舊!
再檢查原理圖。首先看復(fù)位,暈倒,竟然沒有把復(fù)位電路里面用的7404焊上!斷電,找來烙鐵,我焊!
再上電,超級(jí)終端還是沒有反應(yīng),又狂按復(fù)位鍵,還是沒反應(yīng)。
當(dāng)時(shí)心情真是郁悶到了極點(diǎn)!檢查了一下調(diào)試串口的接口芯片,應(yīng)該沒有問題。又仔細(xì)檢查了一下電路圖,先從串口部分看起,突然發(fā)現(xiàn)調(diào)試串口的2,3腳連接順序跟手頭的開發(fā)板不一樣,又仔細(xì)檢查了一下用的串口連接線(別的開發(fā)板上的),原來是直連的,而并非交叉線,還好,手頭有9針的串口接插頭,馬上作了一個(gè)轉(zhuǎn)接的。
連接好以后,再上電,終于在超級(jí)終端上看到了久違的CCCCCCCCCC.。。。。。。
OK,下面可以用U-BOOT和arm-linux來測(cè)試了。
5. U-BOOT移植篇
確定板子可以工作之后,接下來的工作就是把U-BOOT移植到我的板子上。因?yàn)橛蠥T91RM9200DK板移植好的例子,所以移植工作要相對(duì)容易一些。在移植之前,我先用AT91RM9200DK板子上的U-BOOT做了一下測(cè)試,因?yàn)楫?dāng)時(shí)還沒有仔細(xì)研究U-BOOT的結(jié)構(gòu),而現(xiàn)在對(duì)U-BOOT也不是很了解,只能說是皮毛而已,等以后研究明白了再寫一些有關(guān)U-BOOT的文字。首先把現(xiàn)成的U-BOOT下載到我的板子上:
A. 將串口連接好,打開超級(jí)終端,串口參數(shù)設(shè)置為115200,8,none, 1, none。
B. 接通板子電源,超級(jí)終端出現(xiàn)“CCCCC”。
C. 在超級(jí)終端中選擇菜單 transfer=》send file, 傳送協(xié)議選擇xmodem或者1K xmodem,傳送文件選擇loader.bin,文件傳送完畢后超級(jí)終端出現(xiàn)以下提示:
loader 1.0 (Aug 8 2003 - 12:01:07)
XMODEM: Download U-BOOT
然后繼續(xù)顯示“CCCC”
D. 在超級(jí)終端中選擇菜單 transfer=》send file, 傳送協(xié)議選擇xmodem或者1K xmodem,傳送文件選擇u-boot.bin,文件傳送完畢后超級(jí)終端出現(xiàn)u-boot提示符: U-BOOT》
E. 由于我的板子上的PHY接口芯片由DM9161E換成了LXT971A,因此此時(shí)在U-BOOT中網(wǎng)絡(luò)接口是不能使用的,這給下載linux內(nèi)核測(cè)試帶來了麻煩。但為了進(jìn)一步確定板子可以正常工作,我還是用U-BOOT中的串口下載命令loadb將linux內(nèi)核和ramdisk下載到了板子上:
U-BOOT》 loadb 21000000 uImage
U-BOOT》 loadb 21100000 ramdisk-rmk7
U-BOOT》 setenv bootargs root=/dev/ram rw initrd=0x21100000,6000000 ramdisk_size=15360 console=ttyS0,115200 mem=32M
U-BOOT》 bootm 21000000
整個(gè)過程用了一個(gè)多小時(shí),呵呵,太慢了。下載后linux可以啟動(dòng),基本上應(yīng)該沒有問題了。下面的首要任務(wù)就是修改U-BOOT代碼,讓其支持LXT971A,要不然下載linux太費(fèi)時(shí)間了。
6. U-BOOT移植初步
經(jīng)過上述準(zhǔn)備工作之后,基本上確定硬件沒有問題,下一步首要的任務(wù)就是要把板子上的以太網(wǎng)調(diào)通,以方便以后的下載調(diào)試工作。
6.1 準(zhǔn)備工作
在移植之前,我手頭已經(jīng)有一個(gè)Atmel官方提供的U-BOOT源代碼,但不是最新的版本。 因此我首先到U-BOOT的站點(diǎn)下載了最新的版本(sourceforge.net/projects/u-boot), 當(dāng)時(shí)的最新版本是1.1.2 。 另外還需要一個(gè)交叉編譯器。 當(dāng)時(shí)手頭上有arm-linux-gcc-2.95.3版本, 后來又從handhelds.org下載了3.3.2的版本。 版本并不是越高越好,因?yàn)榇嬖诩嫒菪缘膯栴}。 后來在用3.3.2版本編譯atmel提供的linux-2.4.19的時(shí)候,就出現(xiàn)了一堆錯(cuò)誤,但改成2.95.3后就沒有問題了。
*****小插曲******
在做移植準(zhǔn)備的過程中還出現(xiàn)了一個(gè)小小的插曲。 因?yàn)樵诖酥暗挠布y(cè)試工作都是在windows環(huán)境下用超級(jí)終端進(jìn)行的。而交叉編譯需要linux環(huán)境(當(dāng)然在windows下用cygwin也可以,但兼容性不是很好),因此就需要一個(gè)linux環(huán)境下的“超級(jí)終端”,我對(duì)linux并不熟悉,從網(wǎng)上查了一些資料,決定用minicom. 自己經(jīng)過摸索,可以操縱minicom了,但是在用xmodem協(xié)議向板上下載程序的時(shí)候遇到問題: 總是提示錯(cuò)誤,下載無法進(jìn)行。 急忙到google上面搜索相關(guān)資料,結(jié)果發(fā)現(xiàn)這是一個(gè)共性的問題,很多朋友都反映xmodem下載協(xié)議有問題, 據(jù)說是時(shí)序上的原因。 怎么辦呢? 最初從網(wǎng)上當(dāng)了一些有關(guān)xmodem的資料以及一些源代碼, 后來決定自己編寫一個(gè)xmodem下載的程序。 下面就做一個(gè)小小的總結(jié)。
A. xmodem協(xié)議簡(jiǎn)介
XMODEM協(xié)議是一種使用撥號(hào)調(diào)制解調(diào)器的個(gè)人計(jì)算機(jī)通信中廣泛使用的異步文件運(yùn)輸協(xié)議。這種協(xié)議以128字節(jié)塊的形式傳輸數(shù)據(jù),并且每個(gè)塊都使用一個(gè)校驗(yàn)和過程來進(jìn)行錯(cuò)誤檢測(cè)。如果接收方關(guān)于一個(gè)塊的校驗(yàn)和與它在發(fā)送方的校驗(yàn)和相同時(shí),接收方就向發(fā)送方發(fā)送一個(gè)認(rèn)可字節(jié)。然而,這種對(duì)每個(gè)塊都進(jìn)行認(rèn)可的策略將導(dǎo)致低性能,特別是具有很長(zhǎng)傳播延遲的衛(wèi)星連接的情況時(shí),問題更加嚴(yán)重。
使用循環(huán)冗余校驗(yàn)的與XMODEM相應(yīng)的一種協(xié)議稱為XMODEM-CRC。還有一種是XMODEM-1K,它以1024字節(jié)一塊來傳輸數(shù)據(jù)。ZMODEM是最有效的一個(gè)XMODEM版本,它不需要對(duì)每個(gè)塊都進(jìn)行認(rèn)可。事實(shí)上,它只是簡(jiǎn)單地要求對(duì)損壞的塊進(jìn)行重發(fā)。ZMODEM對(duì)按塊收費(fèi)的分組交換網(wǎng)絡(luò)是非常有用的。不需要認(rèn)可回送分組在很大程度上減少了通信量。YMODEM也是一種XMODEM的實(shí)現(xiàn)。它包括XMODEM-1K的所有特征,另外在一次單一會(huì)話期間為發(fā)送一組文件,增加了批處理文件傳輸模式。
有不少產(chǎn)品的維護(hù)和軟件升級(jí)都是采用XMODEM協(xié)議來進(jìn)行的。
B.xmodem協(xié)議的數(shù)據(jù)包格式
首先看幾個(gè)定義: SOH---》 0x01 STX---》0x02 ACK---》0x06 NAK---》0x15 EOT---》0x04 CRC--》 ‘C’ 其中SOH代表一個(gè)數(shù)據(jù)包的開始標(biāo)志,而STX與SOH有相同的含義,不過它是用在1K-XMODEM協(xié)議中的。 ACK是確認(rèn)標(biāo)志,NAK是非確認(rèn)標(biāo)志(要求重發(fā)),EOT是傳送結(jié)束標(biāo)志,CRC是使用CRC校驗(yàn)標(biāo)志。一個(gè)完整數(shù)據(jù)包的格式如下:
《SOH》 《數(shù)據(jù)包長(zhǎng)度》 《255-數(shù)據(jù)包長(zhǎng)度》 《128字節(jié)數(shù)據(jù)》 《校驗(yàn)字》
在1K-XMODEM協(xié)議中,數(shù)據(jù)長(zhǎng)度由128字節(jié)提高到1K字節(jié)。
在XMODEM協(xié)議中,對(duì)數(shù)據(jù)包進(jìn)行校驗(yàn)的方式有兩種,一種是采用校驗(yàn)和,另一種是CRC校驗(yàn)。那么收發(fā)雙方如何確認(rèn)對(duì)方的校驗(yàn)方式呢?
C.傳輸建立過程
在早期采用校驗(yàn)和的XMODEM協(xié)議中,接收方準(zhǔn)備就緒之后,會(huì)間隔一段時(shí)間發(fā)送“NAK”信號(hào),每發(fā)送一個(gè)NAK,接收方就等待一段時(shí)間并檢查是否收到SOH信號(hào),若接收到則開始數(shù)據(jù)傳送; 而發(fā)送方接收到NAK信號(hào)之后,便認(rèn)為接收方已經(jīng)準(zhǔn)備好并開始數(shù)據(jù)傳送,這樣一個(gè)數(shù)據(jù)傳輸過程就建立起來了。在這種方式下采用的是校驗(yàn)和的方式。
在采用CRC校驗(yàn)的XMODEM協(xié)議中,為了保持兼容性,接收方若支持CRC校驗(yàn),間隔發(fā)送的不是NAK而是CRC標(biāo)志,也就是‘C’,看到這里大家可能明白了AT91RM9200片內(nèi)啟動(dòng)之后,為什么向外發(fā)送‘CCC’而不是其他的字符。 發(fā)送方接收到CRC標(biāo)志之后,若支持CRC校驗(yàn)方式,便開始數(shù)據(jù)的傳輸,否則不做任何響應(yīng)。 若接收方兩種校驗(yàn)方式都支持的話(取決于程序編寫),若對(duì)方不支持CRC,它就會(huì)轉(zhuǎn)到校驗(yàn)和方式。
D.數(shù)據(jù)傳輸過程
下面是一個(gè)采用CRC校驗(yàn)方式進(jìn)行數(shù)據(jù)傳遞的過程示意圖:
發(fā)送方 接收方
《----------------------------------------------------- ‘C’
《SOH》 《01》 《fe》 《128字節(jié)》 《CRC高字節(jié)》 《CRC低字節(jié)》 ------------》
《------------------------------------------------------ 《ACK》
《SOH》 《02》 《fd》 《128字節(jié)》 《CRC高字節(jié)》 《CRC低字節(jié)》 -------------》
《----------------------------------------------------- 《NAK》
《SOH》 《02》 《fd》 《128字節(jié)》 《CRC高字節(jié)》 《CRC低字節(jié)》 -------------》
《------------------------------------------------------ 《ACK》
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
《EOT》 -----------------------------------------------------------》
《------------------------------------------------------《NAK》
《EOT》 -----------------------------------------------------------》
《------------------------------------------------------《ACK》
傳送結(jié)束
E. 程序編寫
有了上面的了解,就可以編寫利用XMODEM協(xié)議進(jìn)行數(shù)據(jù)傳送的程序了。 這里面涉及到linux下的串口編程,還有就是16位CRC校驗(yàn)的生成。下面把我寫的源程序給出,供大家參考,程序在RedHat9.0下編譯測(cè)試通過。
/***A simple program using xmodem/1kxmode send file*/
#include 《stdio.h》
#include 《stdlib.h》
#include 《unistd.h》
#include 《sys/types.h》
#include 《sys/stat.h》
#include 《fcntl.h》
#include 《termios.h》
#include 《errno.h》
/*
Xmodem Frame form: 《SOH》《blk #》《255-blk #》《--128 data bytes--》《CRC hi》《CRC lo》
*/
#define XMODEM_SOH 0x01
#define XMODEM_STX 0x02
#define XMODEM_EOT 0x04
#define XMODEM_ACK 0x06
#define XMODEM_NAK 0x15
#define XMODEM_CRC_CHR ‘C’
#define XMODEM_CRC_SIZE 2 /* Crc_High Byte + Crc_Low Byte */
#define XMODEM_FRAME_ID_SIZE 2 /* Frame_Id + 255-Frame_Id */
#define XMODEM_DATA_SIZE_SOH 128 /* for Xmodem protocol */
#define XMODEM_DATA_SIZE_STX 1024 /* for 1K xmodem protocol */
#define USE_1K_XMODEM 0 /* 1 for use 1k_xmodem 0 for xmodem */
#if (USE_1K_XMODEM)
#define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_STX
#define XMODEM_HEAD XMODEM_STX
#else
#define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_SOH
#define XMODEM_HEAD XMODEM_SOH
#endif
/*********/
#define SERIAL_DEVICE “/dev/ttyS0”
#define BAUDRATE B115200;
/***************SUB PROGRAM*******/
unsigned short GetCrc16 ( char *ptr, unsigned short count )
{
unsigned short crc, i;
crc = 0;
while(count--)
{
crc = crc ^ (int) *ptr++ 《《 8;
for(i = 0; i 《 8; i++)
{
if (crc & 0x8000)
crc = crc 《《 1 ^ 0x1021;
else
crc = crc 《《 1;
}
}
return (crc & 0xFFFF);
}
/*******************************/
int Initial_SerialPort(void)
{
int fd;
struct termios options;
fd = open( SERIAL_DEVICE , O_RDWR &line; O_NOCTTY &line; O_NDELAY );
if ( fd == -1 )
{
/*open error!*/
perror(“port can‘t open!”);
return -1;
}
/*Get the current options for the port.。.*/
tcgetattr(fd, &options);
/*Set the baud rates to BAUDRATE.。.*/
cfsetispeed(&options, BAUDRATE);
cfsetospeed(&options, BAUDRATE);
tcsetattr(fd, TCSANOW, &options);
if (0!= tcgetattr(fd, &options))
{
perror(“SetupSerial 1”);
return -1;
}
/*
* 8bit Data,no partity,1 stop bit.。。
*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag &line;= CS8;
tcflush(fd,TCIFLUSH);
/***Choosing Raw Input*/
options.c_lflag &= ~(ICANON &line; ECHO &line; ECHOE &line; ISIG);
options.c_oflag &= ~OPOST;
/*
* Set the new options for the port.。。
*/
if(0!=tcsetattr(fd, TCSANOW, &options))
{
perror(“SetupSerial error”);
return -1 ;
}
return fd ;
}
//******************************
void ClearReceiveBuffer(int fd)
{
unsigned char tmp;
while((read(fd,&tmp,1))》0);
return;
}
//********************************
int main(int argc,char *argv[])
{
int fd;
char data_file_name[80];
char packet_data[ XMODEM_DATA_SIZE ];
char frame_data[ XMODEM_DATA_SIZE + XMODEM_CRC_SIZE + XMODEM_FRAME_ID_SIZE + 1 ];
unsigned char tmp;
FILE *datafile;
int complete,retry_num,pack_counter,read_number,write_number,i;
unsigned short crc_value;
unsigned char ack_id;
//**open serial port1
if ( (fd = Initial_SerialPort()) == -1) return -1 ;
data_file_name = argv[1];
if ((datafile=fopen(data_file_name,“rb”))==NULL)
{
perror(“file can’t open!”);
return -1 ;
}
//*******************************
pack_counter = 0;
complete = 0;
retry_num = 0;
ClearReceiveBuffer(fd);
while((read(fd,&ack_id,1))《=0);
printf(“%c ”,ack_id);
ack_id = XMODEM_ACK;
while(!complete)
{
switch(ack_id)
{
case XMODEM_ACK:
retry_num = 0;
pack_counter++;
read_number = fread( packet_data, sizeof(char), XMODEM_DATA_SIZE, datafile);
if(read_number》0)
{
if (read_number《XMODEM_DATA_SIZE_SOH)
{
printf(“Start filling the last frame! ”);
for(;read_number《XMODEM_DATA_SIZE;read_number++)
packet_data[read_number] = 0x00;
}
frame_data[0] = XMODEM_HEAD;
frame_data[1] = (char)pack_counter;
frame_data[2] = (char)(255-frame_data[1]);
for(i=0;i《XMODEM_DATA_SIZE;i++)
frame_data[i+3]=packet_data[i];
crc_value = GetCrc16(packet_data,XMODEM_DATA_SIZE);
frame_data[XMODEM_DATA_SIZE_SOH+3]=(unsigned char)(crc_value 》》 8);
frame_data[XMODEM_DATA_SIZE_SOH+4]=(unsigned char)(crc_value);
write_number = write( fd, frame_data, XMODEM_DATA_SIZE_SOH + 5);
printf(“waiting for ACK,%d,%d,。。。”,pack_counter,write_number);
while((read(fd,&ack_id,1))《=0);
if(ack_id == XMODEM_ACK)
printf(“Ok! ”);
else
printf(“Error! ”);
break;
}
else
{
ack_id = XMODEM_EOT;
complete = 1;
printf(“Waiting for complete ACK 。。。”);
while(ack_id != XMODEM_ACK) ;
{
ack_id = XMODEM_EOT;
write_number=write(fd,&ack_id,1);
while((read(fd,&ack_id,1))《=0);
}
printf(“ok! ”);
printf(“Sending file complete! ”);
break;
}
case XMODEM_NAK:
if( retry_num++ 》 10)
{
printf(“Retry too many times,Quit! ”);
complete = 1;
break;
}
write_num = write(fd,frame_data,XMODEM_DATA_SIZE + 5);
printf(“Retry for ACK,%d,%d.。。”,pack_counter,write_number);
while((read(fd,&ack_id,1))《=0);
if( ack_id == XMODEM_ACK )
printf(“Ok! ”);
else
printf(“Error! ”);
break;
default:
printf(“Fatal Error! ”);
complete = 1;
break;
}
}
fclose(datafile);
close(fd);
return 0;
}
7. U-BOOT移植之LXT971篇
移植和測(cè)試都是在linux下進(jìn)行的(Redhat 9.0)。 首先將以前下載的U-BOOT-1.1.2源代碼解壓到/usr/local/u-boot-1.1.2, arm-linux-gcc-3.3.2解壓到/usr/local/arm/3.3.2, 設(shè)置好路徑:
export PATH=/usr/local/arm/3.3.2/bin:$PATH ( 告訴系統(tǒng)去哪里找 arm-linux- )
打開u-boot-1.1.2下面的readme文件, 根據(jù)里面的提示, 要將U-BOOT移植到一個(gè)新板上,需要做以下改動(dòng):
A. 修改根目錄下的Makefile以及MAKEFILE文件,向其中增加對(duì)你要新添加的板子的支持。 因?yàn)橛蠥T91RM9200DK項(xiàng)做參考,所以這一步并不困難;
B. 在/board下面新建一個(gè)目錄,里面包含你要增加的板子的信息。 我給我的板起名為at91rm9200my(呵呵,不夠響亮), 那么我要做的就是在/board下新建一個(gè)at91rm9200my的目錄, 根據(jù)readme里面的提示, 至少要包含這幾個(gè)文件: Makefile , at91rm9200my.c, flash.c 和 u-boot.lds, 有at91rm9200DK做參考,這一步也不困難。 (拷貝過來就OK了,我還沒有根據(jù)我的板子做修改)
C. 在 /include/configs/ 下面建一個(gè)新板的配置文件, 我的是 at91rm9200my.h, 至于里面的內(nèi)容,當(dāng)然是參考at91rm9200dk.h了。
D. 做完上面這些, 下面就是要做LXT971A的工作了。 at91rm9200dk上用的是DM9161E, 在/board/at91rm9200dk里面我找到了dm9161.c 這個(gè)文件, 那么我需要做的就是要改動(dòng)這個(gè)文件了。 另外在Makefile里面我還看到了這么一行: OBJS := at91rm9200dk.o at45.o dm9161.o flash.o 我想這兩個(gè)文件是需要我改動(dòng)的了。首先把dm9161.c文件另存為lxt971a.c, 把Makefile里面的那行改為:
OBJS := at91rm9200dk.o at45.o lxt971a.o flash.o
根據(jù)我的了解,DM9161是RMII接口,LXT971A是MII接口,而對(duì)PHY的控制是通過MDI來進(jìn)行的,在DM9161.C里面,主要有這么幾個(gè)函數(shù):
dm9161_IsPhyConnected()
dm9161_GetLinkSpeed()
dm9161_InitPhy()
dm9161_AutoNegotiate()
at91rm92000_GetPhyInterface()
除了最后一個(gè)外,前四個(gè)函數(shù)都是通過at91rm9200提供的MDI接口對(duì)PHY進(jìn)行控制,那么我要做的工作就是根據(jù)LXT971A的手冊(cè)對(duì)這個(gè)函數(shù)改寫。 DM9161與LXT971A內(nèi)部的寄存器地址大部分都是相同的,只有少數(shù)幾個(gè)的地址和位定義不同,改寫比較容易。 下面是我改寫完的 lxt971a.c :
#include 《at91rm9200_net.h》
#include 《net.h》
#include 《lxt971a.h》 /***這個(gè)頭文件u-boot源文件里面有***/
#ifdef CONFIG_DRIVER_ETHER
#if (CONFIG_COMMANDS & CFG_CMD_NET)
static unsigned int lxt971a_IsPhyConnected (AT91PS_EMAC p_mac)
{
unsigned short Id1, Id2;
at91rm9200_EmacEnableMDIO (p_mac);
at91rm9200_EmacReadPhy (p_mac, PHY_COMMON_ID1, &Id1);
at91rm9200_EmacReadPhy (p_mac, PHY_COMMON_ID2, &Id2);
at91rm9200_EmacDisableMDIO (p_mac);
if ((Id1 == PHY_LXT971A))
return TRUE;
return FALSE;
}
static UCHAR lxt971a_GetLinkSpeed (AT91PS_EMAC p_mac)
{
unsigned short stat1, stat2;
if (!at91rm9200_EmacReadPhy (p_mac, PHY_COMMON_STAT, &stat1))
return FALSE;
if (?。╯tat1 & PHY_COMMON_STAT_LNK_STAT)) /* link status up? */
return FALSE;
if (!at91rm9200_EmacReadPhy (p_mac, PHY_LXT971_STAT2, &stat2))
return FALSE;
if ((stat1 & PHY_COMMON_STAT_100BXFD) && (stat2 & PHY_LXT971_STAT2_100BTX) && (stat2 & PHY_LXT971_STAT2_DUPLEX_MODE)) {
/*set Emac for 100BaseTX and Full Duplex */
p_mac-》EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD;
return TRUE;
}
if ((stat1 & PHY_COMMON_STAT_10BTFD) && !(stat2 & PHY_LXT971_STAT2_100BTX) && (stat2 & PHY_LXT971_STAT2_DUPLEX_MODE)) {
/*set MII for 10BaseT and Full Duplex */
p_mac-》EMAC_CFG = (p_mac-》EMAC_CFG &
~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
| AT91C_EMAC_FD;
return TRUE;
}
if ((stat1 & PHY_COMMON_STAT_100BXHD) && (stat2 & PHY_LXT971_STAT2_100BTX) && ?。╯tat2 & PHY_LXT971_STAT2_DUPLEX_MODE)) {
/*set MII for 100BaseTX and Half Duplex */
p_mac-》EMAC_CFG = (p_mac-》EMAC_CFG &
~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
| AT91C_EMAC_SPD;
return TRUE;
}
if ((stat1 & PHY_COMMON_STAT_10BTHD) && !(stat2 & PHY_LXT971_STAT2_100BTX) && ?。╯tat2 & PHY_LXT971_STAT2_DUPLEX_MODE)) {
/*set MII for 10BaseT and Half Duplex */
p_mac-》EMAC_CFG &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
return TRUE;
}
return FALSE;
}
static UCHAR lxt971a_InitPhy (AT91PS_EMAC p_mac)
{
UCHAR ret = TRUE;
unsigned short IntValue;
at91rm9200_EmacEnableMDIO (p_mac);
if (!lxt971a_GetLinkSpeed (p_mac)) {
/* Try another time */
ret = lxt971a_GetLinkSpeed (p_mac);
}
/* Disable PHY Interrupts */
at91rm9200_EmacReadPhy (p_mac, PHY_LXT971_INT_ENABLE, &IntValue);
/* clear FDX, SPD, Link, INTR masks */
IntValue &= ~(PHY_LXT971_INT_ENABLE_DUPLEXMSK | PHY_LXT971_INT_ENABLE_SPEEDMSK |
PHY_LXT971_INT_ENABLE_LINKMSK | PHY_LXT971_INT_ENABLE_TINT);
at91rm9200_EmacWritePhy (p_mac, PHY_LXT971_INT_ENABLE, &IntValue);
at91rm9200_EmacDisableMDIO (p_mac);
return (ret);
}
static UCHAR lxt971a_AutoNegotiate (AT91PS_EMAC p_mac, int *status)
{
unsigned short value;
unsigned short PhyAnar;
unsigned short PhyAnalpar;
/* Set lxt971a control register */
if (!at91rm9200_EmacReadPhy (p_mac, PHY_COMMON_CTRL, &value))
return FALSE;
value &= ~PHY_COMMON_CTRL_AUTO_NEG; /* remove autonegotiation enable */
value |= PHY_COMMON_CTRL_ISOLATE; /* Electrically isolate PHY */
if (!at91rm9200_EmacWritePhy (p_mac, PHY_COMMON_CTRL, &value))
return FALSE;
/* Set the Auto_negotiation Advertisement Register */
/* MII advertising for Next page, 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3 */
PhyAnar = PHY_COMMON_AUTO_ADV_NP | PHY_COMMON_AUTO_ADV_100BTXFD | PHY_COMMON_AUTO_ADV_100BTX |
PHY_COMMON_AUTO_ADV_10BTFD | PHY_COMMON_AUTO_ADV_10BT | PHY_COMMON_AUTO_ADV_802_3;
if (!at91rm9200_EmacWritePhy (p_mac, PHY_COMMON_AUTO_ADV, &PhyAnar))
return FALSE;
/* Read the Control Register */
if (!at91rm9200_EmacReadPhy (p_mac, PHY_COMMON_CTRL, &value))
return FALSE;
value |= PHY_COMMON_CTRL_SPD_100 | PHY_COMMON_CTRL_AUTO_NEG | PHY_COMMON_CTRL_DUPLEX;
if (!at91rm9200_EmacWritePhy (p_mac, PHY_COMMON_CTRL, &value))
return FALSE;
/* Restart Auto_negotiation */
value |= PHY_COMMON_CTRL_RES_AUTO;
if (!at91rm9200_EmacWritePhy (p_mac, PHY_COMMON_CTRL, &value))
return FALSE;
/*check AutoNegotiate complete */
udelay (30000);
at91rm9200_EmacReadPhy (p_mac, PHY_COMMON_STAT, &value);
if (?。╲alue & PHY_COMMON_STAT_AN_COMP))
return FALSE;
/* Get the AutoNeg Link partner base page */
if (!at91rm9200_EmacReadPhy (p_mac, PHY_COMMON_AUTO_LNKB, &PhyAnalpar))
return FALSE;
if ((PhyAnar & PHY_COMMON_AUTO_ADV_100BTXFD) && (PhyAnalpar & PHY_COMMON_AUTO_LNKB_100BTXFD)) {
/*set MII for 100BaseTX and Full Duplex */
p_mac-》EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD;
return TRUE;
}
if ((PhyAnar & PHY_COMMON_AUTO_ADV_10BTFD) && (PhyAnalpar & PHY_COMMON_AUTO_LNKB_10BTFD)) {
/*set MII for 10BaseT and Full Duplex */
p_mac-》EMAC_CFG = (p_mac-》EMAC_CFG &
~(AT91C_EMAC_SPD | AT91C_EMAC_FD))
| AT91C_EMAC_FD;
return TRUE;
}
return FALSE;
}
/*
* Name:
* at91rm92000_GetPhyInterface
* Description:
* Initialise the interface functions to the PHY
* Arguments:
* None
* Return value:
* None
*/
void at91rm92000_GetPhyInterface(AT91PS_PhyOps p_phyops)
{
p_phyops-》Init = lxt971a_InitPhy;
p_phyops-》IsPhyConnected = lxt971a_IsPhyConnected;
p_phyops-》GetLinkSpeed = lxt971a_GetLinkSpeed;
p_phyops-》AutoNegotiate = lxt971a_AutoNegotiate;
}
#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
#endif /* CONFIG_DRIVER_ETHER */
8. 關(guān)于板子的配制文件
改寫完網(wǎng)絡(luò)部分以后,我將U-BOOT用arm-linux-gcc-3.3.2做了編譯:
$ make mrproper
$ make at91rm9200my_config
$ make all
將生成的u-boot.bin下載到我的板子上,結(jié)果發(fā)現(xiàn)網(wǎng)絡(luò)部分還是不能用。 仔細(xì)考慮了一下可能出問題的幾個(gè)地方:
A. 硬件問題? 網(wǎng)線插上之后LAX971A的三個(gè)狀態(tài)指示都正常,應(yīng)該不是PHY問題, 又想會(huì)不會(huì)是自己做的板子的問題(2層板,100M的網(wǎng)卡速度比較高), 后來又否定了自己的想法, 不應(yīng)該一點(diǎn)反應(yīng)都沒有,因?yàn)閁-BOOT沒有提示MII方面的錯(cuò)誤, 如果是板子布線方面的問題的話, 應(yīng)該是出現(xiàn)不穩(wěn)定現(xiàn)象。
B. 軟件問題? 后來想如果真的是板子的原因,那可真是慘了,因?yàn)榫W(wǎng)卡是必須要用的。 因此我決定先從軟件方面找原因。 既然LXT971和DM9161接口方式不同(一個(gè)是MII,一個(gè)是RMII),那么在U-BOOT中應(yīng)該有這方面的設(shè)置選項(xiàng),在什么地方呢? 首先想到的就是移植板子的時(shí)候在/include/configs/下面添加的配制文件 at91rm9200my.h, 這個(gè)文件我是從at91rm9200dk復(fù)制過來的,里面有這么一個(gè)與RMII接口有關(guān)的配制項(xiàng) #define CONFIG_AT91C_USE_RMII, 當(dāng)時(shí)我是把它改成了#define CONFIG_AT91C_USE_RMII 0, 會(huì)不會(huì)是這里的問題呢? 那么這個(gè)選項(xiàng)影響哪個(gè)文件呢? 因?yàn)樵赿m9161.c里面沒有發(fā)現(xiàn)與這個(gè)定義有關(guān)的語句, 后來用sourceinsight( 閱讀源代碼的好工具哦) 在/cpu/at91rm9200/下面找到了這個(gè)文件: at91rm9200_eth.c 在這個(gè)文件里面有個(gè)函數(shù) eth_init() 是用來對(duì)MAC進(jìn)行初始化的, 應(yīng)該就是它了,很快就找到了與RMII相關(guān)的那條語句:
#if defined(CONFIG_AT91C_USE_RMII) && !defined(CONFIG_CMC_PU2)
*AT91C_PIOB_PDR = AT91C_PB25_EF100 |
AT91C_PB19_ERXCK | AT91C_PB18_ECOL | AT91C_PB17_ERXDV |
AT91C_PB16_ERX3 | AT91C_PB15_ERX2 | AT91C_PB14_ETXER |
AT91C_PB13_ETX3 | AT91C_PB12_ETX2;
而其上面的語句是:
*AT91C_PIOA_PDR = AT91C_PA16_EMDIO | AT91C_PA15_EMDC | AT91C_PA14_ERXER |
AT91C_PA13_ERX1 | AT91C_PA12_ERX0 | AT91C_PA11_ECRS_ECRSDV |
AT91C_PA10_ETX1 | AT91C_PA9_ETX0 | AT91C_PA8_ETXEN |
AT91C_PA7_ETXCK_EREFCK;
這兩段語句都是與設(shè)置PIO有關(guān)的,也就是將PIO設(shè)置成MAC的工作方式, 通過分析可以看出第二段是RMII和MII都需要進(jìn)行的,而第一段是根據(jù)CONFIG_AT91C_USE_RMII是否定義來判斷的,而不是我最初理解的將CONFIG_AT91C_USE_RMII定義為0就可以了(呵呵,比較菜) , 重新對(duì)at91rm9200my.h做修改,將
#define CONFIG_AT91C_USE_RMII 改成 #undef CONFIG_AT91C_USE_RMII
然后重新編譯,下載, OK, 板上的網(wǎng)口終于起來了。
另外在用U-BOOT提供的tftp下載linux內(nèi)核和根文件系統(tǒng)的時(shí)候,還遇到一個(gè)問題,就是在linux下, tftp服務(wù)默認(rèn)設(shè)置是不自動(dòng)啟動(dòng)的,所以要修改/etc/xinet.d/ 下面的tftp配制文件,將里面的 disable = yes 改為 no或者把這一行注釋掉。 另外還有一個(gè)問題,就是記得把linux的防火墻(我用的是redhat9.0)關(guān)掉,要不然也無法用tftp下載。 詳細(xì)的下載過程后面接著說。
9. linux內(nèi)核移植
對(duì)U-BOOT 做了簡(jiǎn)單的修改,使其網(wǎng)絡(luò)部分可以使用之后,接下來就是讓linux也能認(rèn)出我的PHY來。
9.1 內(nèi)核修改
我用的內(nèi)核源文件是atmel提供的linux-2.4.19-rmk7, 在對(duì)源文件做修改之前, 首先編譯試驗(yàn)了一下,結(jié)果發(fā)現(xiàn)用arm-linux-gcc-3.3.2編譯有問題(U-BOOT是用3.3.2編譯的),沒辦法,又把2.95.3裝上,再試,沒有問題。
接下來就是要確定要修改哪些文件了。 linux內(nèi)核源文件的層次還是比較清楚的,我很快在/drivers/at91/net/下面找到了at91_ether.h 和 at91_ether.c 這兩個(gè)個(gè)文件, 把這兩個(gè)文件打開看了一些, 覺得這就是我要找的。 在at91_ether.h里面找到了這么幾行定義:
#define MII_DM9161_ID 0x0181b880 /*****PHY的ID***/
#define MII_DSCSR_REG 17 /***PHY的內(nèi)部寄存器地址***/
#define MII_DSINTR_REG 21 /****PHY的內(nèi)部寄存器地址***/
根據(jù)前面在修改U-BOOT的時(shí)候的得到的信息, 這三個(gè)定義是與LXT971A不同的,根據(jù)LXT971A的手冊(cè), 做了以下修改,增加了下面幾行定義:
#define MII_LXT971A_ID 0x001378e0 /****對(duì)應(yīng)MII_DM9161_ID
#define MII_LXT971_INT_ENABLE 0x12 /***對(duì)應(yīng)MII_DSCSR_REG
#define MII_LXT971_INT_STATUS 0x13 /***對(duì)應(yīng)MII_DSINTR_REG
然后對(duì) at91_ether.c 里面的PHY管理部分做相應(yīng)修改如下:
static int update_linkspeed(struct net_device *dev, AT91PS_EMAC regs) {
unsigned int bmsr, bmcr, lpa, mac_cfg;
unsigned int speed, duplex;
/* Link status is latched, so read twice to get current value */
read_phy(regs, MII_BMSR, &bmsr);
read_phy(regs, MII_BMSR, &bmsr);
if (?。╞msr & BMSR_LSTATUS)) return -1; /* no link */
read_phy(regs, MII_BMCR, &bmcr);
if (bmcr & BMCR_ANENABLE) { /* AutoNegotiation is enabled */
if (!(bmsr & BMSR_ANEGCOMPLETE)) return -2; /* auto-negotitation in progress */
read_phy(regs, MII_LPA, &lpa);
if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
else speed = SPEED_10;
if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
else duplex = DUPLEX_HALF;
} else {
speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
}
/* Update the MAC */
mac_cfg = regs-》EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
if (speed == SPEED_100) {
if (duplex == DUPLEX_FULL) /* 100 Full Duplex */
regs-》EMAC_CFG = mac_cfg | AT91C_EMAC_SPD | AT91C_EMAC_FD;
else /* 100 Half Duplex */
regs-》EMAC_CFG = mac_cfg | AT91C_EMAC_SPD;
} else {
if (duplex == DUPLEX_FULL) /* 10 Full Duplex */
regs-》EMAC_CFG = mac_cfg | AT91C_EMAC_FD;
else /* 10 Half Duplex */
regs-》EMAC_CFG = mac_cfg;
}
printk(KERN_INFO “%s: Link now %i-%s ”, dev-》name, speed, (duplex == DUPLEX_FULL) ? “FullDuplex” : “HalfDuplex”);
return 0;
}
/*
* Handle interrupts from the PHY
*/
void at91ether_phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
AT91PS_EMAC emac = (AT91PS_EMAC) dev-》base_addr;
int status;
unsigned int phy;
enable_mdi(emac);
read_phy(emac, MII_LXT971_INT_STATUS, &phy); /* acknowledge interrupt in PHY */
status = AT91_SYS-》PIOC_ISR; /* acknowledge interrupt in PIO */
status = update_linkspeed(dev, emac);
if (status == -1) { /* link is down */
netif_carrier_off(dev);
printk(KERN_INFO “%s: Link down. ”, dev-》name);
} else if (status == -2) { /* auto-negotiation in progress */
/* Do nothing - another interrupt generated when negotiation complete */
} else { /* link is operational */
netif_carrier_on(dev);
}
disable_mdi(emac);
}
/*
* Initialize and enable the PHY interrupt when link-state changes
*/
void enable_phyirq(struct net_device *dev, AT91PS_EMAC regs)
{
struct at91_private *lp = (struct at91_private *) dev-》priv;
unsigned int dsintr, status;
static int first_init = 0;
if (first_init == 0) {
// TODO: Check error code. Really need a generic PIO (interrupt)
// layer since we‘re really only interested in the PC4 line.
(void) request_irq(4, at91ether_phy_interrupt, 0, dev-》name, dev);
/* AT91_SYS-》PIOC_ODR = AT91C_PIO_PC4; Configure as input */
AT91_SYS-》PIOC_ODR = AT91C_PIO_PB29;
first_init = 1;
}
else {
status = AT91_SYS-》PIOC_ISR; /* clear any pending PIO interrupts */
AT91_SYS-》PIOC_IER = AT91C_PIO_PB29; /* Enable interrupt */
spin_lock_irq(&lp-》lock);
enable_mdi(regs);
read_phy(regs, MII_LXT971_INT_ENABLE, &dsintr);
dsintr = dsintr | 0x00f2; /* set bits 7..4 and 1 */
write_phy(regs, MII_LXT971_INT_ENABLE, dsintr);
disable_mdi(regs);
spin_unlock_irq(&lp-》lock);
}
}
/*
* Disable the PHY interrupt
*/
void disable_phyirq(struct net_device *dev, AT91PS_EMAC regs)
{
struct at91_private *lp = (struct at91_private *) dev-》priv;
unsigned int dsintr;
spin_lock_irq(&lp-》lock);
enable_mdi(regs);
read_phy(regs, MII_LXT971_INT_ENABLE, &dsintr);
dsintr = dsintr & 0x00f2; /* clear bits 8..11 */
write_phy(regs, MII_LXT971_INT_ENABLE, dsintr);
disable_mdi(regs);
spin_unlock_irq(&lp-》lock);
AT91_SYS-》PIOC_IDR = AT91C_PIO_PB29; /* Disable interrupt */
}
int at91ether_probe(struct net_device *dev)
{
AT91PS_EMAC regs = (AT91PS_EMAC) AT91C_VA_BASE_EMAC;
unsigned int phyid1, phyid2;
int detected = -1;
/* Configure the hardware - RMII vs MII mode */
#ifdef CONFIG_AT91_ETHER_RMII
AT91_CfgPIO_EMAC_RMII();
#else
AT91_CfgPIO_EMAC_MII();
#endif
AT91_SYS-》PMC_PCER = 1 《《 AT91C_ID_EMAC; /* Enable Peripheral clock */
/* Read the PHY ID registers */
enable_mdi(regs);
read_phy(regs, MII_PHYSID1, &phyid1);
read_phy(regs, MII_PHYSID2, &phyid2);
disable_mdi(regs);
if (((phyid1 《《 16) | (phyid2 & 0xfff0)) == MII_LXT971A_ID) {
detected = at91ether_setup(dev);
}
AT91_SYS-》PMC_PCDR = 1 《《 AT91C_ID_EMAC; /* Disable Peripheral clock */
return detected;
}
另外,是否使用RMII接口在/include/config/at91/ether下面的rmii.h中定義
#define CONFIG_AT91_ETHER_RMII 1 將其改為
#undef CONFIG_AT91_ETHER_RMII
做完上述修改之后,就可以進(jìn)行編譯了。
9.2 內(nèi)核的編譯下載和執(zhí)行
內(nèi)核編譯過程如下:
$ make at91rm9200dk_config
$ make oldconfig
如果想調(diào)整內(nèi)核, $ make menuconfig
$ make bzImage
編譯完后在/arch/arm/boot下生成映像文件。 如果想生成供U-BOOT下載使用的uImage文件, 接著執(zhí)行:
$ /usr/local/arm/2.95.3/bin/arm-linux-objcopy -O binary -S vmlinux linux.bin
$ gzip -v9 linux.bin
$ mkimage -A arm -O linux -C gzip -a 0x20008000 -e 0x20008000 -d linux.bin.gz uImage
生成uImage以后,就可以用U-BOOT來下載并啟動(dòng)linux內(nèi)核了,過程如下:(假設(shè)U-BOOT已經(jīng)運(yùn)行)
在linux主機(jī)下將uImage和ramdisk-rmk7拷貝到/tftpboot下
U-BOOT》 setenv ethaddr 00:11:22:33:44:55:66
U-BOOT》 setenv ipaddr 10.10.155.200
U-BOOT》 setenv serverip 10.10.155.211
U-BOOT》 tftp 21000000 uImage
U-BOOT》 tftp 21100000 ramdisk-rmk7
U-BOOT》 setenv bootargs root=/dev/ram rw initrd=0x21100000,6000000 ramdisk_size=15360 console=ttyS0,115200 mem=32M
U-BOOT》 bootm 21000000
如果沒有問題,就會(huì)看到linux的啟動(dòng)信息.linux內(nèi)核啟動(dòng)之后, 用root (無密碼) 登錄。 如果想使用網(wǎng)絡(luò),還需要進(jìn)行一些配置,例如:
?。踨oot@AT91RM9200DK /root]$ ifconfig eth0 down
?。踨oot@AT91RM9200DK /root]$ ifconfig eth0 10.10.155.2 up
另外,默認(rèn)情況下是不可以更改9200的MAC地址的,如果想更改,在編譯內(nèi)核的時(shí)候,需要修改相應(yīng)的頭文件。
花了兩天的時(shí)間對(duì)前面的調(diào)試工作做了總結(jié), 雖然這其中的很多東西對(duì)我來說都是第一次, 但總的來說過程還算順利, 雖然遇到了不少的問題, 但都得到了比較好的解決, 在這里特別感謝網(wǎng)絡(luò)上不知名的朋友們的幫助。 到現(xiàn)在為止, 工作才剛剛開始, 軟件方面還有大量的工作需要去做, 希望自己能延續(xù)自己在前一段時(shí)間的好運(yùn)氣, 盡快將軟件寫完調(diào)通。 這也是我第一次使用linux, 第一次接觸開源軟件, 雖然以前也用C,但是接觸了linux,讀了其他優(yōu)秀的源代碼,突然感覺以前自己的寫的C是多么的native, 多么的缺乏組織,呵呵。 就先寫這么多了,以后有時(shí)間再寫吧。
基于AT91RM9200 處理器系統(tǒng)中BootLoader與內(nèi)核的參數(shù)傳遞
本文著重介BootLoader與內(nèi)核之間 參數(shù)傳遞 這一基本功能。本文的硬件平臺(tái)是基于AT91RM9200 處理器系統(tǒng),軟件平臺(tái)是Linux-2.6.1...
2018-03-28 標(biāo)簽:內(nèi)核at91rm9200bootLoader 1950 0
AT91RM9200的UBOOT啟動(dòng)燒寫過程詳解
不同廠商的出的Soc片子在啟動(dòng)方式大都提供片內(nèi)和片外啟動(dòng)兩種方式,一般都是在片內(nèi)固化一段小程序方便于程序開發(fā)而已。
2018-06-18 標(biāo)簽:at91rm9200uboot 5786 0
基于ARM芯片AT91RM9200的無線打印模塊的硬件平臺(tái)設(shè)計(jì)
在ARM芯片AT91RM9200上構(gòu)建了 無線打印模塊 的硬件平臺(tái),在Android操作系統(tǒng)上完成了軟件平臺(tái)的搭建,通過調(diào)用Linux內(nèi)核的CUPS,實(shí)...
2018-02-07 標(biāo)簽:armat91rm9200 1735 0
基于AT91RM9200系統(tǒng)電源的設(shè)計(jì)與調(diào)試
隨著計(jì)算機(jī)技術(shù)、半導(dǎo)體技術(shù)以及電子技術(shù)的發(fā)展,嵌入式系統(tǒng)以其體積小、可靠性高、功耗低、軟硬件集成度高等特點(diǎn)廣泛應(yīng)用于工業(yè)制造、過程控制、通信、儀器、儀表...
2014-08-28 標(biāo)簽:AT91RM9200系統(tǒng)電源 1813 0
基于ARM9的多行列鍵盤設(shè)計(jì)及其驅(qū)動(dòng)實(shí)現(xiàn)
論文展示了一種在ARM等嵌入式設(shè)備上擴(kuò)展特殊鍵盤的新設(shè)計(jì)方法,并以運(yùn)行ARM-Linux操作系統(tǒng)的AT91RM9200系統(tǒng)為例,對(duì)鍵盤接口電路設(shè)計(jì)和鍵盤...
2012-05-29 標(biāo)簽:鍵盤AT91RM9200驅(qū)動(dòng)程序 2014 0
3
0
嵌入式視頻監(jiān)控系統(tǒng)視頻服務(wù)器該怎么設(shè)計(jì)?
標(biāo)簽:AT91RM9200視頻服務(wù)器視頻監(jiān)控系統(tǒng) 1839 3
4
0
AT91RM9200的嵌入式網(wǎng)絡(luò)攝像系統(tǒng)該怎么設(shè)計(jì)?
標(biāo)簽:網(wǎng)絡(luò)攝像機(jī)AT91RM9200 1589 4
淺談嵌入式視頻監(jiān)控系統(tǒng)設(shè)計(jì)方案立即下載
類別:嵌入式開發(fā) 2017-10-17 標(biāo)簽:at91rm9200
詳解AT91RM9200的嵌入式網(wǎng)絡(luò)攝像機(jī)立即下載
類別:嵌入式開發(fā) 2017-10-17 標(biāo)簽:at91rm9200
AT91RM9200的手持設(shè)備的低功耗設(shè)計(jì)立即下載
類別:單片機(jī) 2017-10-15 標(biāo)簽:手持設(shè)備AT91RM9200
類別:嵌入式開發(fā) 2017-09-29 標(biāo)簽:處理器電路AT91RM9200
at91rm9200 linux開發(fā)經(jīng)驗(yàn)吐血分享(涵紅外驅(qū)動(dòng)案例)立即下載
類別:嵌入式開發(fā) 2017-09-01 標(biāo)簽:linuxat91rm9200
基于ARM芯片at91rm9200的嵌入式溫度控制系統(tǒng)的設(shè)計(jì)立即下載
類別:工控技術(shù) 2017-09-01 標(biāo)簽:嵌入式溫度控制at91rm9200
工業(yè)級(jí)AT91RM9200核心板原理圖立即下載
類別:信號(hào)處理電路 2016-10-27 標(biāo)簽:原理圖AT91RM9200核心板
獨(dú)家公布工業(yè)級(jí)AT91RM9200核心板原理圖pcb立即下載
類別:信號(hào)處理電路 2016-07-06 標(biāo)簽:原理圖AT91RM9200核心板
類別:產(chǎn)品手冊(cè) 2016-01-11 標(biāo)簽:AT91RM9200
嵌入式視頻監(jiān)控系統(tǒng)視頻服務(wù)器的設(shè)計(jì)與實(shí)現(xiàn)立即下載
類別:嵌入式開發(fā) 2015-08-24 標(biāo)簽:視頻監(jiān)控AT91RM9200MPEG-4
基于ARM平臺(tái)的RFID系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)
本文提出了一種基于ARM 平臺(tái)的RFID 系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)方案,以滿足人們?cè)谇度胧筋I(lǐng)域?qū)FID技術(shù)的開發(fā)與應(yīng)用。
2012-11-14 標(biāo)簽:ARMRFIDAT91RM9200 1776 0
車載GPS定位終端在過去十年內(nèi)已經(jīng)成為汽車工業(yè)發(fā)展的焦點(diǎn)。在歐美國(guó)家和日本,車載GPS定位終端在最近幾年內(nèi)得以廣泛的應(yīng)用。車載GPS定位終端是融全球衛(wèi)星...
2011-10-27 標(biāo)簽:GPSARM9AT91RM9200 2532 0
基于ARM的新型智能交通信號(hào)燈系統(tǒng)設(shè)計(jì)
本文提出了一種具有分布式特征的交通信號(hào)燈控制系統(tǒng)設(shè)計(jì)方案,它利用RFID技術(shù)提高路況信息的收集精度, 利用電流環(huán)遠(yuǎn)距離傳輸方式,并且應(yīng)用人工智能理論使得...
2011-10-19 標(biāo)簽:ARMAT91RM9200交通信號(hào)燈 5009 0
隨著網(wǎng)絡(luò)經(jīng)濟(jì)時(shí)代的到來,基于TCP/IP協(xié)議的IP網(wǎng)的應(yīng)用得到廣泛普及,利用網(wǎng)絡(luò)資源可以實(shí)現(xiàn)設(shè)備的網(wǎng)絡(luò)接入,設(shè)備聯(lián)網(wǎng)監(jiān)控已經(jīng)成為工業(yè)自動(dòng)化的發(fā)展趨勢(shì)。
2011-10-11 標(biāo)簽:IP網(wǎng)絡(luò)AT91RM9200多串口協(xié)議 1678 0
本文利用 ATMEL公司 的 AT91RM9200型微處理器 和 Philips公司的 UDA1341型立體聲音頻編解碼器設(shè)計(jì)了一種嵌入式音頻系統(tǒng)。該嵌...
2011-09-19 標(biāo)簽:音頻ARM9AT91RM9200 1971 0
基于AT91RM9200的嵌入式ARM開發(fā)平臺(tái)的設(shè)計(jì)
嵌入式系統(tǒng)是以應(yīng)用為中心,以計(jì)算機(jī)技術(shù)為基礎(chǔ),軟硬件可以裁剪來適應(yīng)系統(tǒng)對(duì)功能、可靠性、成本、體積、功耗要求嚴(yán)格的專用計(jì)算機(jī)體系。隨著各種微處理器功能的完...
2011-09-16 標(biāo)簽:ARM嵌入式AT91RM9200 1235 0
基于ARM9處理器AT91RM9200和MCP25lO的CA
隨著現(xiàn)場(chǎng)總線技術(shù)高速發(fā)展和標(biāo)準(zhǔn)化程度的不斷提高,以現(xiàn)場(chǎng)總線技術(shù)為基礎(chǔ)的開放型集散測(cè)控系統(tǒng)得到廣泛應(yīng)用??偩€是控制器局域網(wǎng)(controller are...
2010-08-18 標(biāo)簽:ARM9at91rm9200AT91R 2183 0
VxWorks是美國(guó)Wind River公司開發(fā)的嵌入式實(shí)時(shí)操作系統(tǒng),具有高性能、可裁減性好等特點(diǎn),能支持多種微處理器(如PowerPC、X85
2010-07-29 標(biāo)簽:ATVxWorksat91rm9200 1675 0
AT91RM9200設(shè)計(jì)的保數(shù)據(jù)采集方案
1、 應(yīng)用背景 環(huán)保信息網(wǎng)絡(luò)承載著環(huán)保信息監(jiān)測(cè)預(yù)警服務(wù),為了保障環(huán)保數(shù)據(jù)的不間斷采集
2010-07-22 標(biāo)簽:ARMat91rm9200AT91RM 937 0
AT91RM9200的導(dǎo)航計(jì)算機(jī)測(cè)試儀設(shè)計(jì)
AT91RM9200的導(dǎo)航計(jì)算機(jī)測(cè)試儀設(shè)計(jì) 0 概述導(dǎo)航計(jì)算機(jī)是捷聯(lián)組合導(dǎo)航組件的組成部件,可接收來自多路輸入數(shù)據(jù)接口的數(shù)據(jù),并將結(jié)果由輸出...
2010-04-01 標(biāo)簽:AT91RM9200 1049 0
編輯推薦廠商產(chǎn)品技術(shù)軟件/工具OS/語言教程專題
電機(jī)控制 | DSP | 氮化鎵 | 功率放大器 | ChatGPT | 自動(dòng)駕駛 | TI | 瑞薩電子 |
BLDC | PLC | 碳化硅 | 二極管 | OpenAI | 元宇宙 | 安森美 | ADI |
無刷電機(jī) | FOC | IGBT | 逆變器 | 文心一言 | 5G | 英飛凌 | 羅姆 |
直流電機(jī) | PID | MOSFET | 傳感器 | 人工智能 | 物聯(lián)網(wǎng) | NXP | 賽靈思 |
步進(jìn)電機(jī) | SPWM | 充電樁 | IPM | 機(jī)器視覺 | 無人機(jī) | 三菱電機(jī) | ST |
伺服電機(jī) | SVPWM | 光伏發(fā)電 | UPS | AR | 智能電網(wǎng) | 國(guó)民技術(shù) | Microchip |
Arduino | BeagleBone | 樹莓派 | STM32 | MSP430 | EFM32 | ARM mbed | EDA |
示波器 | LPC | imx8 | PSoC | Altium Designer | Allegro | Mentor | Pads |
OrCAD | Cadence | AutoCAD | 華秋DFM | Keil | MATLAB | MPLAB | Quartus |
C++ | Java | Python | JavaScript | node.js | RISC-V | verilog | Tensorflow |
Android | iOS | linux | RTOS | FreeRTOS | LiteOS | RT-THread | uCOS |
DuerOS | Brillo | Windows11 | HarmonyOS |