0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

標(biāo)簽 > AT91RM9200

AT91RM9200

+關(guān)注 0人關(guān)注

AT91RM9200-QU是一種微處理器,數(shù)據(jù)總線寬度是32 bit,而本專題詳細(xì)記載了AT91RM9200開發(fā)調(diào)試手記,并且在設(shè)計(jì)路徑、電路結(jié)構(gòu)設(shè)計(jì)等都有詳細(xì)的說明,對工程師開發(fā)AT91RM9200設(shè)計(jì)有很大的幫助。

文章: 17 個(gè)
瀏覽: 14850
帖子: 8 個(gè)

AT91RM9200簡介

 自己的AT91RM9200的板子已經(jīng)調(diào)試了一段時(shí)間了,從開始動(dòng)手制作PCB到現(xiàn)在,差不多有半年的時(shí)間了。在這期間一直忙著查資料,畫板布線,聯(lián)系制板廠家,聯(lián)系購買器件(呵呵,大小活全包),一直沒有時(shí)間寫寫總結(jié)之類的東西,另外平時(shí)也沒有養(yǎng)成隨時(shí)總結(jié)的好習(xí)慣。以前搞硬件基本上是以8位的51單片機(jī)為主,偶爾也用用PC104,AVR之類的控制器,其他16位、32位的控制器從沒用過,對其感覺甚為神秘。因此在做這塊板子之前,自己查閱了很多資料(網(wǎng)上資料為主,資源豐富,比較方便),在做了各種權(quán)衡利弊之后(做方案,選芯片是比較令人頭疼的事情,有過系統(tǒng)設(shè)計(jì)經(jīng)歷的朋友可能有這種體會(huì)),最后才痛下決心,決定選用atmel的AT91RM9200做為控制芯片。因?yàn)樵诖酥皬膩頉]有搞過32位的東東,所以當(dāng)時(shí)心里一點(diǎn)底都沒有。

AT91RM9200百科

  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)系購買器件(呵呵,大小活全包),一直沒有時(shí)間寫寫總結(jié)之類的東西,另外平時(shí)也沒有養(yǎng)成隨時(shí)總結(jié)的好習(xí)慣。以前搞硬件基本上是以8位的51單片機(jī)為主,偶爾也用用PC104,AVR之類的控制器,其他16位、32位的控制器從沒用過,對其感覺甚為神秘。因此在做這塊板子之前,自己查閱了很多資料(網(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)用場合比較特殊:野外應(yīng)用,因此在設(shè)計(jì)方案的時(shí)候盡量選用工業(yè)級的芯片。第一次用這款控制器,設(shè)計(jì)電路的時(shí)候最好的參考就是由atmel官方提供的開發(fā)板:AT91RM9200DK。但是這塊板上的網(wǎng)絡(luò)PHY部分采用的是DM9161E,查資料發(fā)現(xiàn)這個(gè)PHY非工業(yè)級產(chǎn)品,后來決定把它換成intel的LXT971A。另外我的應(yīng)用中還需要一個(gè)網(wǎng)絡(luò)接口,在非PCI接口的網(wǎng)絡(luò)控制芯片中選來選去,最后決定用SMSC公司的LAN91C111I-NE,也是一款工業(yè)級別的芯片(網(wǎng)上資料反映其功耗較大,power hungry,但其他工業(yè)級的片子當(dāng)時(shí)沒有查到,繆辦法呀)。其他的電路基本上都是參考AT91RM9200DK的原理圖設(shè)計(jì)的,除了復(fù)位電路采用了阻容電路(開發(fā)板上那個(gè)復(fù)位芯片國內(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)橹瓢骞に嚨脑?,頗費(fèi)一般周折之后才把板子交出去(拿到深圳做的,很羨慕在深圳工作的朋友,買器件制板都很方便)。一周之后,終于拿到了樣板。做工看上去蠻不錯(cuò),比在本地做的強(qiáng)多了。

  3.焊接檢查

  板子做完了,器件也買好了,下面就要焊接調(diào)試了。當(dāng)時(shí)心里是比較緊張的,因?yàn)槲易龅腜CB是雙面板,當(dāng)時(shí)網(wǎng)上有朋友告訴我說雙面板可能會(huì)不穩(wěn)定(9200能跑到200MHz),另外對自己的布線水平也沒信心(我對自己的定位是:啥都會(huì),啥都不精)。板子上除了一個(gè)按鍵和幾個(gè)接插件,全部都是表貼。本地有專門提供焊接服務(wù)的,找到他們之后,2個(gè)小時(shí)半塊板子搞定(為什么是半塊?因?yàn)橛幸徊糠旨]有買齊,就是那個(gè)LAN91C111I-NE)。板子焊接完之后拿回來,在上電測試之前,按照我以前的習(xí)慣,先用萬用表量了一下板子的電源和地。這一量不要緊,驚出我一身冷汗:短路!心情一下子就#?。?@!#@!,怎么搞的嘛!沒別的辦法,檢查吧。首先確定是不是焊接的原因?qū)е碌?,樣板一共做?0塊,拿另外一塊空板量了一下,暈倒!也是短路!

  板子上到處是電源和地,怎么檢查呢?我心里知道這種錯(cuò)誤最難檢查了,要命的是我的板子已經(jīng)焊接好了,要是萬一短路的地方在表貼件的下面,那豈不是太殘酷了?我心里一邊暗自禱告,一邊找來一塊板做我的犧牲品,各位可能知道我下一步要做什么了,嘿嘿,從電源輸入的地方開始,逐條把分支割斷。一共割了6刀,終于找到了短路的地方(其中有一處是憑俺肉眼瞅出來的)。短路原因是鋪的銅跟電源線太近而短路(這其中有加工方面的因素,另一方面也是因?yàn)槲以O(shè)置的間距太小了,0.3mm,以后還是用1mm好了)。又在焊接好的板子上割了兩刀,萬用表一測,OK!這次是運(yùn)氣好,以后在焊接之前可要好好測試板子有沒有問題了。

  上面的短路故障是因?yàn)榧庸さ脑驅(qū)е碌?。后來又焊接了一塊板,也出現(xiàn)了短路的問題,是復(fù)位線和地線短路,與上面不同的是,這次短路是因?yàn)楹附訉?dǎo)致的。所以在焊接前后一定要檢查。這兩次都算我運(yùn)氣好,沒有出現(xiàn)燒毀芯片的問題。雖然是比較低級的錯(cuò)誤,但有時(shí)卻是致命的。

  4.初步調(diào)試

  確定板子沒有問題之后(至少自己感覺是這樣),下一步就是檢查板子工作是否正常了。根據(jù)手頭掌握的資料,9200從片內(nèi)啟動(dòng)之后,會(huì)通過DEBGUG串口向外發(fā)送‘CCCCC‘字符(至于這個(gè)C字符代表什么含義,接下來會(huì)有描述)。OK,先從這里入手。首先啟動(dòng)超級終端,參數(shù)設(shè)置為115200,8,no,1,no;

  將調(diào)試串口連到PC串口,給板子上電。

  超級終端無反應(yīng),按復(fù)位鍵,濤聲依舊!

  再檢查原理圖。首先看復(fù)位,暈倒,竟然沒有把復(fù)位電路里面用的7404焊上!斷電,找來烙鐵,我焊!

  再上電,超級終端還是沒有反應(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)接的。

  連接好以后,再上電,終于在超級終端上看到了久違的CCCCCCCCCC.。。。。。。

  OK,下面可以用U-BOOT和arm-linux來測試了。

  5. U-BOOT移植篇

  確定板子可以工作之后,接下來的工作就是把U-BOOT移植到我的板子上。因?yàn)橛蠥T91RM9200DK板移植好的例子,所以移植工作要相對容易一些。在移植之前,我先用AT91RM9200DK板子上的U-BOOT做了一下測試,因?yàn)楫?dāng)時(shí)還沒有仔細(xì)研究U-BOOT的結(jié)構(gòu),而現(xiàn)在對U-BOOT也不是很了解,只能說是皮毛而已,等以后研究明白了再寫一些有關(guān)U-BOOT的文字。首先把現(xiàn)成的U-BOOT下載到我的板子上:

  A. 將串口連接好,打開超級終端,串口參數(shù)設(shè)置為115200,8,none, 1, none。

  B. 接通板子電源,超級終端出現(xiàn)“CCCCC”。

  C. 在超級終端中選擇菜單 transfer=》send file, 傳送協(xié)議選擇xmodem或者1K xmodem,傳送文件選擇loader.bin,文件傳送完畢后超級終端出現(xiàn)以下提示:

  loader 1.0 (Aug 8 2003 - 12:01:07)

  XMODEM: Download U-BOOT

  然后繼續(xù)顯示“CCCC”

  D. 在超級終端中選擇菜單 transfer=》send file, 傳送協(xié)議選擇xmodem或者1K xmodem,傳送文件選擇u-boot.bin,文件傳送完畢后超級終端出現(xiàn)u-boot提示符: U-BOOT》

  E. 由于我的板子上的PHY接口芯片由DM9161E換成了LXT971A,因此此時(shí)在U-BOOT中網(wǎng)絡(luò)接口是不能使用的,這給下載linux內(nèi)核測試帶來了麻煩。但為了進(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試工作都是在windows環(huán)境下用超級終端進(jìn)行的。而交叉編譯需要linux環(huán)境(當(dāng)然在windows下用cygwin也可以,但兼容性不是很好),因此就需要一個(gè)linux環(huán)境下的“超級終端”,我對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é)議簡介

  XMODEM協(xié)議是一種使用撥號調(diào)制解調(diào)器的個(gè)人計(jì)算機(jī)通信中廣泛使用的異步文件運(yùn)輸協(xié)議。這種協(xié)議以128字節(jié)塊的形式傳輸數(shù)據(jù),并且每個(gè)塊都使用一個(gè)校驗(yàn)和過程來進(jìn)行錯(cuò)誤檢測。如果接收方關(guān)于一個(gè)塊的校驗(yàn)和與它在發(fā)送方的校驗(yàn)和相同時(shí),接收方就向發(fā)送方發(fā)送一個(gè)認(rèn)可字節(jié)。然而,這種對每個(gè)塊都進(jìn)行認(rèn)可的策略將導(dǎo)致低性能,特別是具有很長傳播延遲的衛(wèi)星連接的情況時(shí),問題更加嚴(yán)重。

  使用循環(huán)冗余校驗(yàn)的與XMODEM相應(yīng)的一種協(xié)議稱為XMODEM-CRC。還有一種是XMODEM-1K,它以1024字節(jié)一塊來傳輸數(shù)據(jù)。ZMODEM是最有效的一個(gè)XMODEM版本,它不需要對每個(gè)塊都進(jìn)行認(rèn)可。事實(shí)上,它只是簡單地要求對損壞的塊進(jìn)行重發(fā)。ZMODEM對按塊收費(fèi)的分組交換網(wǎng)絡(luò)是非常有用的。不需要認(rèn)可回送分組在很大程度上減少了通信量。YMODEM也是一種XMODEM的實(shí)現(xiàn)。它包括XMODEM-1K的所有特征,另外在一次單一會(huì)話期間為發(fā)送一組文件,增加了批處理文件傳輸模式。

  有不少產(chǎn)品的維護(hù)和軟件升級都是采用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ù)包長度》 《255-數(shù)據(jù)包長度》 《128字節(jié)數(shù)據(jù)》 《校驗(yàn)字》

  在1K-XMODEM協(xié)議中,數(shù)據(jù)長度由128字節(jié)提高到1K字節(jié)。

  在XMODEM協(xié)議中,對數(shù)據(jù)包進(jìn)行校驗(yàn)的方式有兩種,一種是采用校驗(yàn)和,另一種是CRC校驗(yàn)。那么收發(fā)雙方如何確認(rèn)對方的校驗(yàn)方式呢?

  C.傳輸建立過程

  在早期采用校驗(yàn)和的XMODEM協(xié)議中,接收方準(zhǔn)備就緒之后,會(huì)間隔一段時(shí)間發(fā)送“NAK”信號,每發(fā)送一個(gè)NAK,接收方就等待一段時(shí)間并檢查是否收到SOH信號,若接收到則開始數(shù)據(jù)傳送; 而發(fā)送方接收到NAK信號之后,便認(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)方式都支持的話(取決于程序編寫),若對方不支持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下編譯測試通過。

  /***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篇

  移植和測試都是在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文件,向其中增加對你要新添加的板子的支持。 因?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接口,而對PHY的控制是通過MDI來進(jìn)行的,在DM9161.C里面,主要有這么幾個(gè)函數(shù):

  dm9161_IsPhyConnected()

  dm9161_GetLinkSpeed()

  dm9161_InitPhy()

  dm9161_AutoNegotiate()

  at91rm92000_GetPhyInterface()

  除了最后一個(gè)外,前四個(gè)函數(shù)都是通過at91rm9200提供的MDI接口對PHY進(jìn)行控制,那么我要做的工作就是根據(jù)LXT971A的手冊對這個(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) && ?。╯tat2 & 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() 是用來對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就可以了(呵呵,比較菜) , 重新對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)核移植

  對U-BOOT 做了簡單的修改,使其網(wǎng)絡(luò)部分可以使用之后,接下來就是讓linux也能認(rèn)出我的PHY來。

  9.1 內(nèi)核修改

  我用的內(nèi)核源文件是atmel提供的linux-2.4.19-rmk7, 在對源文件做修改之前, 首先編譯試驗(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的手冊, 做了以下修改,增加了下面幾行定義:

  #define MII_LXT971A_ID 0x001378e0 /****對應(yīng)MII_DM9161_ID

  #define MII_LXT971_INT_ENABLE 0x12 /***對應(yīng)MII_DSCSR_REG

  #define MII_LXT971_INT_STATUS 0x13 /***對應(yīng)MII_DSINTR_REG

  然后對 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.

 ?。╲oid) 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í)間對前面的調(diào)試工作做了總結(jié), 雖然這其中的很多東西對我來說都是第一次, 但總的來說過程還算順利, 雖然遇到了不少的問題, 但都得到了比較好的解決, 在這里特別感謝網(wǎng)絡(luò)上不知名的朋友們的幫助。 到現(xiàn)在為止, 工作才剛剛開始, 軟件方面還有大量的工作需要去做, 希望自己能延續(xù)自己在前一段時(shí)間的好運(yùn)氣, 盡快將軟件寫完調(diào)通。 這也是我第一次使用linux, 第一次接觸開源軟件, 雖然以前也用C,但是接觸了linux,讀了其他優(yōu)秀的源代碼,突然感覺以前自己的寫的C是多么的native, 多么的缺乏組織,呵呵。 就先寫這么多了,以后有時(shí)間再寫吧。

查看詳情

at91rm9200技術(shù)

基于AT91RM9200 處理器系統(tǒng)中BootLoader與內(nèi)核的參數(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 1876 0

AT91RM9200的UBOOT啟動(dòng)燒寫過程詳解

不同廠商的出的Soc片子在啟動(dòng)方式大都提供片內(nèi)和片外啟動(dòng)兩種方式,一般都是在片內(nèi)固化一段小程序方便于程序開發(fā)而已。

2018-06-18 標(biāo)簽:at91rm9200uboot 5653 0

基于ARM芯片AT91RM9200的無線打印模塊的硬件平臺(tái)設(shè)計(jì)

基于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 1655 0

基于AT91RM9200系統(tǒng)電源的設(shè)計(jì)與調(diào)試

基于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)電源 1756 0

基于ARM9的多行列鍵盤設(shè)計(jì)及其驅(qū)動(dòng)實(shí)現(xiàn)

基于ARM9的多行列鍵盤設(shè)計(jì)及其驅(qū)動(dòng)實(shí)現(xiàn)

論文展示了一種在ARM等嵌入式設(shè)備上擴(kuò)展特殊鍵盤的新設(shè)計(jì)方法,并以運(yùn)行ARM-Linux操作系統(tǒng)的AT91RM9200系統(tǒng)為例,對鍵盤接口電路設(shè)計(jì)和鍵盤...

2012-05-29 標(biāo)簽:鍵盤AT91RM9200驅(qū)動(dòng)程序 1986 0

查看更多>>

at91rm9200資料下載

查看更多>>

at91rm9200資訊

基于ARM平臺(tái)的RFID系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)

本文提出了一種基于ARM 平臺(tái)的RFID 系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)方案,以滿足人們在嵌入式領(lǐng)域?qū)FID技術(shù)的開發(fā)與應(yīng)用。

2012-11-14 標(biāo)簽:ARMRFIDAT91RM9200 1722 0

基于ARM9的車載GPS定位終端設(shè)計(jì)

基于ARM9的車載GPS定位終端設(shè)計(jì)

車載GPS定位終端在過去十年內(nèi)已經(jīng)成為汽車工業(yè)發(fā)展的焦點(diǎn)。在歐美國家和日本,車載GPS定位終端在最近幾年內(nèi)得以廣泛的應(yīng)用。車載GPS定位終端是融全球衛(wèi)星...

2011-10-27 標(biāo)簽:GPSARM9AT91RM9200 2460 0

基于ARM的新型智能交通信號燈系統(tǒng)設(shè)計(jì)

本文提出了一種具有分布式特征的交通信號燈控制系統(tǒng)設(shè)計(jì)方案,它利用RFID技術(shù)提高路況信息的收集精度, 利用電流環(huán)遠(yuǎn)距離傳輸方式,并且應(yīng)用人工智能理論使得...

2011-10-19 標(biāo)簽:ARMAT91RM9200交通信號燈 4911 0

多串口通訊協(xié)議轉(zhuǎn)換案例

隨著網(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ā)展趨勢。

2011-10-11 標(biāo)簽:IP網(wǎng)絡(luò)AT91RM9200多串口協(xié)議 1623 0

基于ARM9的音頻系統(tǒng)設(shè)計(jì)

基于ARM9的音頻系統(tǒng)設(shè)計(jì)

本文利用 ATMEL公司 的 AT91RM9200型微處理器 和 Philips公司的 UDA1341型立體聲音頻編解碼器設(shè)計(jì)了一種嵌入式音頻系統(tǒng)。該嵌...

2011-09-19 標(biāo)簽:音頻ARM9AT91RM9200 1945 0

基于AT91RM9200的嵌入式ARM開發(fā)平臺(tái)的設(shè)計(jì)

基于AT91RM9200的嵌入式ARM開發(fā)平臺(tái)的設(shè)計(jì)

嵌入式系統(tǒng)是以應(yīng)用為中心,以計(jì)算機(jī)技術(shù)為基礎(chǔ),軟硬件可以裁剪來適應(yīng)系統(tǒng)對功能、可靠性、成本、體積、功耗要求嚴(yán)格的專用計(jì)算機(jī)體系。隨著各種微處理器功能的完...

2011-09-16 標(biāo)簽:ARM嵌入式AT91RM9200 1203 0

基于ARM9處理器AT91RM9200和MCP25lO的CA

基于ARM9處理器AT91RM9200和MCP25lO的CA

 隨著現(xiàn)場總線技術(shù)高速發(fā)展和標(biāo)準(zhǔn)化程度的不斷提高,以現(xiàn)場總線技術(shù)為基礎(chǔ)的開放型集散測控系統(tǒng)得到廣泛應(yīng)用。總線是控制器局域網(wǎng)(controller are...

2010-08-18 標(biāo)簽:ARM9at91rm9200AT91R 2135 0

VxWorks移植到AT91RM9200的BSP定制過程

VxWorks移植到AT91RM9200的BSP定制過程

VxWorks是美國Wind River公司開發(fā)的嵌入式實(shí)時(shí)操作系統(tǒng),具有高性能、可裁減性好等特點(diǎn),能支持多種微處理器(如PowerPC、X85

2010-07-29 標(biāo)簽:ATVxWorksat91rm9200 1629 0

AT91RM9200設(shè)計(jì)的保數(shù)據(jù)采集方案

1、  應(yīng)用背景     環(huán)保信息網(wǎng)絡(luò)承載著環(huán)保信息監(jiān)測預(yù)警服務(wù),為了保障環(huán)保數(shù)據(jù)的不間斷采集

2010-07-22 標(biāo)簽:ARMat91rm9200AT91RM 890 0

AT91RM9200的導(dǎo)航計(jì)算機(jī)測試儀設(shè)計(jì)

AT91RM9200的導(dǎo)航計(jì)算機(jī)測試儀設(shè)計(jì)

AT91RM9200的導(dǎo)航計(jì)算機(jī)測試儀設(shè)計(jì) 0 概述導(dǎo)航計(jì)算機(jī)是捷聯(lián)組合導(dǎo)航組件的組成部件,可接收來自多路輸入數(shù)據(jù)接口的數(shù)據(jù),并將結(jié)果由輸出...

2010-04-01 標(biāo)簽:AT91RM9200 998 0

查看更多>>

at91rm9200數(shù)據(jù)手冊

相關(guān)標(biāo)簽

相關(guān)話題

換一批
  • AMS1117
    AMS1117
    +關(guān)注
    AMS1117系列穩(wěn)壓器有可調(diào)版與多種固定電壓版,設(shè)計(jì)用于提供1A輸出電流且工作壓差可低至1V。在最大輸出電流時(shí),AMS1117器件的最小壓差保證不超過1.3V,并隨負(fù)載電流的減小而逐漸降低。
  • 電機(jī)控制芯片
    電機(jī)控制芯片
    +關(guān)注
  • MSP430G2553
    MSP430G2553
    +關(guān)注
    德州儀器(TI)MSP430系列超低功耗微控制器包含多種器件,它們特有面向多種應(yīng)用的不同外設(shè)集。這種架構(gòu)與5種低功耗模式相組合,專為在便攜式測量應(yīng)用中延長電池使用壽命而優(yōu)化。該器件具有一個(gè)強(qiáng)大的16位 RISCCPU,16位寄存器和有助于獲得最大編碼效率的常數(shù)發(fā)生器。
  • 24c02
    24c02
    +關(guān)注
  • nRF51822
    nRF51822
    +關(guān)注
  • 反向電壓
    反向電壓
    +關(guān)注
    反向電壓是什么意思?反向電壓怎么產(chǎn)生的?我們這邊為大家分享一下正向電壓和反向電壓的區(qū)別;光電效應(yīng)反向電壓;解讀最大反向電壓怎么求?二極管最高反向工作電壓?最高反向工作電壓的計(jì)算公式等知識點(diǎn)。
  • MPU-6050
    MPU-6050
    +關(guān)注
    MPU-6000(6050)為全球首例整合性6軸運(yùn)動(dòng)處理組件,相較于多組件方案,免除了組合陀螺儀與加速器時(shí)間軸之差的問題,減少了大量的封裝空間。
  • 電芯
    電芯
    +關(guān)注
  • eV1527
    eV1527
    +關(guān)注
  • 74hc245
    74hc245
    +關(guān)注
    總線收發(fā)器,典型的CMOS型三態(tài)緩沖門電路,八路信號收發(fā)器,。由于單片機(jī)或CPU的數(shù)據(jù)/地址/控制總線端口都有一定的負(fù)載能力,如果負(fù)載超過其負(fù)載能力,一般應(yīng)加驅(qū)動(dòng)器。
  • 基準(zhǔn)電壓
    基準(zhǔn)電壓
    +關(guān)注
      基準(zhǔn)電壓是指傳感器置于0℃的溫場(冰水混合物),在通以工作電流(100μA)的條件下,傳感器上的電壓值。實(shí)際上就是0點(diǎn)電壓。其表示符號為V(0),該值出廠時(shí)標(biāo)定,由于傳感器的溫度系數(shù)S相同,則只要知道基準(zhǔn)電壓值V(0),即可求知任何溫度點(diǎn)上的傳感器電壓值,而不必對傳感器進(jìn)行分度。
  • IN4007
    IN4007
    +關(guān)注
  • cnn
    cnn
    +關(guān)注
  • ad623
    ad623
    +關(guān)注
  • max3232
    max3232
    +關(guān)注
    MAX3232 器件由兩個(gè)線路驅(qū)動(dòng)器、兩個(gè)線路接收器和一個(gè)雙路電荷泵電路組成,具有端子間(串行端口連接端子,包括 GND)±15kV ESD 保護(hù)。
  • 半橋驅(qū)動(dòng)芯片
    半橋驅(qū)動(dòng)芯片
    +關(guān)注
  • 74HC138
    74HC138
    +關(guān)注
  • ISD1820
    ISD1820
    +關(guān)注
  • MLX90615
    MLX90615
    +關(guān)注
  • EG8010
    EG8010
    +關(guān)注
  • DA轉(zhuǎn)換器
    DA轉(zhuǎn)換器
    +關(guān)注
    DA轉(zhuǎn)換器一般指數(shù)模轉(zhuǎn)換器。它是把數(shù)字量轉(zhuǎn)變成模擬的器件。D/A轉(zhuǎn)換器基本上由4個(gè)部分組成,即權(quán)電阻網(wǎng)絡(luò)、運(yùn)算放大器、基準(zhǔn)電源和模擬開關(guān)。模數(shù)轉(zhuǎn)換器中一般都要用到數(shù)模轉(zhuǎn)換器,模數(shù)轉(zhuǎn)換器即A/D轉(zhuǎn)換器,簡稱ADC,它是把連續(xù)的模擬信號轉(zhuǎn)變?yōu)殡x散的數(shù)字信號的器件。
  • TTP223
    TTP223
    +關(guān)注
    TTP223是觸摸鍵檢測IC,提供1個(gè)觸摸鍵。觸摸檢測IC是為了用可變面積的鍵取代傳統(tǒng)的按鈕鍵而設(shè)計(jì)的。低功耗和寬工作電壓是觸摸鍵的DC和AC特點(diǎn)。111
  • 1N4148
    1N4148
    +關(guān)注
  • lm741
    lm741
    +關(guān)注
  • max485
    max485
    +關(guān)注
    MAX485是一個(gè)八引腳的RS485電平收發(fā)器(只能單工或半雙工)。內(nèi)部含有一個(gè)輸入信號接收器R、一個(gè)輸出信號驅(qū)動(dòng)器D。
  • PCB元件
    PCB元件
    +關(guān)注
  • 6n137
    6n137
    +關(guān)注
  • DK112
    DK112
    +關(guān)注
  • l7805
    l7805
    +關(guān)注
  • SM7525
    SM7525
    +關(guān)注
換一批

關(guān)注此標(biāo)簽的用戶(1人)

118114

編輯推薦廠商產(chǎn)品技術(shù)軟件/工具OS/語言教程專題