>>Drew的主頁(yè)---->硬件驅(qū)動(dòng)
硬件驅(qū)動(dòng)編程
這里主要是涉及硬件驅(qū)動(dòng)編程的問(wèn)題,許多是drew在論壇和E-MAIL上和網(wǎng)友探討過(guò)的一些問(wèn)題,有些是個(gè)人編程經(jīng)驗(yàn).不一定全面.一些相關(guān)程序代碼會(huì)陸續(xù)補(bǔ)到 程序示例 上.
系統(tǒng)初始化
可參見(jiàn) PowerPC初始化示例 和 ARM_Boot示例
Cache的初始化
ARM9的BSP,在romInit()函數(shù)里對(duì)cache進(jìn)行的操作為: 1.設(shè)置幾個(gè)cache區(qū); 2.flush caches(通過(guò)以下代碼實(shí)現(xiàn): LDR R0,=0x00000000 MCR p15,0,R0,c7,c5,0 MCR p15,0,R0,c7,c6,0 ) 問(wèn)題: 1.flush cache是什么意思? 2.在romInit()函數(shù)里一般對(duì)cache進(jìn)行的操作是什么?
1.flush cache是什么意思? 使所有的 IDC 無(wú)效,這樣CPU讀取數(shù)據(jù)和指令時(shí)可以直接到原存儲(chǔ)地址去讀取,而不必從cache中得到,因?yàn)閏ache保留的是以前的數(shù)據(jù),而當(dāng)前原地址的數(shù)據(jù)可能發(fā)生了變化,這樣保證了數(shù)據(jù)的正確性.使CPU得到最新的數(shù)據(jù),當(dāng)然,這樣會(huì)降低CPU的處理速度.
2.在romInit()函數(shù)里一般對(duì)cache進(jìn)行的操作是什么? 在romInit()函數(shù)里,對(duì)cache主要的操作就是flush cache,因?yàn)閷?duì)系統(tǒng)初始化前,必須要保證初始化過(guò)程的正確和連續(xù),所以要有flush cache,disable interrupt 等操作.
VxWorks系統(tǒng)裝入ARM的過(guò)程
問(wèn)題:開(kāi)發(fā)基于ARM7和VxWorks的嵌入式系統(tǒng),Tornado/VxWorks 和一個(gè)基于ARM7TDMI的單板機(jī)是否足夠了?VxWorks 怎么樣裝入單板機(jī)運(yùn)行?不用JEENI可以裝入么?
把 VXWORKS IMGAGE 裝入ARM 的過(guò)程大體上是這樣的: ARM 7 內(nèi)部有 128 BYTE 的 BOOT ROM,和 2K 的 SRAM,當(dāng)需要DOWNLOAD VXWORKS 時(shí) ARM 采用 BOOT 方式啟動(dòng)運(yùn)行存在 BOOTROM 中的程序初始化 ARM 內(nèi)部的 COM 口,從 COM 口接受數(shù)據(jù)到 2K 的 SRAM,這 2K 程序是用來(lái)真正 LOAD VXWORKS 的,2K 程序 LOAD 完畢后系統(tǒng)自動(dòng)跳轉(zhuǎn)到這 2K 程序執(zhí)行它的作用是首先通過(guò) COM 口接受 VXWORKS 到 DRAM ,然后由 DRAM 寫(xiě)入 FLASH 。
寫(xiě)入完畢后,切換到 NORMAL 模式重新啟動(dòng)系統(tǒng),系統(tǒng)自動(dòng)跳到 FLASH 0X00000000 開(kāi)始運(yùn)行 VXWORKS。
可以用 PC 機(jī)上的 COM1 與 ARM 內(nèi)部的 UART1(COM) 通信來(lái) DOWNLOAD VXWORKS。
Bootloader怎么得到,如果對(duì)開(kāi)發(fā)板有些改動(dòng),還能使用開(kāi)發(fā)板的bootloader嗎?bootloader起到什么作用?
Bootloader相當(dāng)于PC機(jī)主板上的BIOS,是最底層的引導(dǎo)軟件,初始化主板的基本設(shè)置,為接收外部程序做硬件上的準(zhǔn)備.
有些bootloader已經(jīng)嵌在CPU內(nèi)了,沒(méi)有bootloader的CPU可以在片外的eeprom內(nèi)做bootloader,也可以不要bootloader,直接通過(guò)JTAG口灌入程序,開(kāi)發(fā)板改動(dòng)基本上不會(huì)影響bootloader.
VxWorks 下的驅(qū)動(dòng)的問(wèn)題
問(wèn)題:vxworks中有兩種驅(qū)動(dòng)模式,一個(gè)是是分層結(jié)構(gòu),特別對(duì)網(wǎng)絡(luò)協(xié)議棧來(lái)說(shuō)有network protocol/MUX/network driver(END,BSD).還有一種就是沒(méi)有層次的概念,在應(yīng)用程序中直接訪問(wèn)硬件的。比方說(shuō)現(xiàn)在有兩種類型的驅(qū)動(dòng),譬如USB 和ATM,他們需要直接交換數(shù)據(jù),不想走OS那一套標(biāo)準(zhǔn)的流程,也就是我們想用后面的一種(OS Independent)。應(yīng)如何去做?
我沒(méi)有做過(guò) ATM,USB 的驅(qū)動(dòng),在 VXWORKS 上做過(guò)其它驅(qū)動(dòng), MODEM,SPI等,我認(rèn)為如果 VXWORKS 不支持莫種協(xié)議的話,可以在 VXWORKS 上直接對(duì)硬件操作,自己按照相關(guān)協(xié)議標(biāo)準(zhǔn)封裝數(shù)據(jù)包按照硬件定義放入相應(yīng)的地址空間。這等于自己寫(xiě)協(xié)議和驅(qū)動(dòng)。
這種方法是可行的,當(dāng)然如能找到 VXWORKS 下支持該協(xié)議的驅(qū)動(dòng)更好。
這種程序和 VXWORKS 系統(tǒng)也是相關(guān)的:
1。MMU 對(duì)該硬件的地址映射正確 (改 BSP ) 2。中斷向量表(改 BSP ) 3。硬件中斷登記 (INTCONNECT ),及 ISR 4。系統(tǒng)任務(wù)協(xié)調(diào),保證在該程序執(zhí)行時(shí),沒(méi)有其它任務(wù)占用 CPU
基本上和開(kāi)發(fā)其它的驅(qū)動(dòng)程序是一樣的。
返回頁(yè)首
硬件中斷
參見(jiàn) 硬件中斷示例
中斷編程中應(yīng)該注意的問(wèn)題
1.中斷程序的調(diào)試不能用單步執(zhí)行,因?yàn)橹袛喟l(fā)生很快,無(wú)法跟蹤。
2.中斷例程中盡量不要用C,庫(kù)函數(shù).因?yàn)橹袛嗵幚碇兴械娜蝿?wù)都被掛起。
3.在中斷調(diào)試過(guò)程中輪詢方式簡(jiǎn)明,易于調(diào)試。在實(shí)時(shí)多任務(wù)程序中肯定用中斷方式,不能用輪詢。
中斷出錯(cuò)時(shí)調(diào)試檢查的方法(以ARM IRQ中斷為例)
1。確定一下是否中斷發(fā)生,在中斷發(fā)生時(shí),查中斷標(biāo)志寄存器INTST1中相應(yīng)的IRQ為是否置1,或用示波器量該IRQ管腳。有中斷產(chǎn)生且中斷enable,就應(yīng)該執(zhí)行相應(yīng)的ISR。
2。如上面沒(méi)有問(wèn)題,仍不執(zhí)行,再查一下是否有比該IRQ等級(jí)更高的中斷持續(xù)發(fā)生屏蔽了該IRQ中斷。
特別要注意一些FIQ中斷,在ARM中FIQ中斷永遠(yuǎn)高于IRQ,可能會(huì)導(dǎo)致IRQ中斷不被執(zhí)行。 在中斷屏蔽寄存器INTMR1中屏蔽所有優(yōu)先級(jí)高于該IRQ的FIQ,會(huì)disable這些FIQ.
請(qǐng)高手指引:在C語(yǔ)言下EP7312,怎樣將中斷(比如:EINT1)與一段需要執(zhí)行的程序掛鉤。這里先謝謝啦! |
EP72xx定義IRQ的中斷向量地址為0x18,你可以在該地址處放一跳轉(zhuǎn)指令,跳到你的中斷處理函數(shù)(IRQHandler),這個(gè)中斷處理函數(shù)的主要作用是根據(jù)中斷標(biāo)志寄存器的標(biāo)志位來(lái)分析IRQ中斷類別(EINT1,EINT2...),然好根據(jù)中斷的類別跳轉(zhuǎn)到相應(yīng)的中斷服務(wù)程序(ISR)進(jìn)行處理. 大概步驟基本如上,不過(guò)一般這些程序是操作系統(tǒng)已經(jīng)有的,用相應(yīng)的函數(shù)(如intConnect)直接使用即可. 你不會(huì)是在寫(xiě)操作系統(tǒng)吧?
另外,ARM的中斷有FIQ和IRQ,FIQ的優(yōu)先級(jí)總是高于IRQ的優(yōu)先級(jí),由于某些操作系統(tǒng)本身的問(wèn)題,可能導(dǎo)致有時(shí)FIQ的中斷屏蔽了IRQ的中斷,使IRQ中斷不能及時(shí)響應(yīng),這種情況下,可能需要從新寫(xiě)這些程序來(lái)進(jìn)行替換.
不知這些是否對(duì)你有所幫助. |
Re:Re:請(qǐng)高手指引:EP7312的中斷 |
您好!
我是個(gè)新手,資料也不全,您說(shuō)的intConnect函數(shù)我沒(méi)有查到,您能告訴我它的功能,基本用法嗎?謝謝!
|
Re:Re:Re:請(qǐng)高手指引:EP7312的中斷 |
intConnect()是VxWorks的函數(shù),如果你的操作系統(tǒng)不是VxWorks,就不能用這個(gè)函數(shù),你的操作系統(tǒng)也應(yīng)該提供類似的函數(shù),你可以找找看.這個(gè)函數(shù)主要是把中斷和中斷例程聯(lián)系起來(lái).就是解決你提到的問(wèn)題. |
Re:Re:Re:Re:請(qǐng)高手指引:EP7312的中斷 |
謝謝您, 我的操作系統(tǒng)是linux的,有類似的函數(shù)嗎? 再問(wèn):怎樣在EP72xx中斷向量地址為0x18中放置一跳轉(zhuǎn)指令(比如 goto:),跳到中斷處理函數(shù)呢? |
Re:Re:Re:Re:Re:請(qǐng)高手指引:EP7312的中斷 |
linux操作系統(tǒng)下,函數(shù)應(yīng)該是request_irq(),你可以查一下這個(gè)函數(shù)的具體用法.
不過(guò),我建議最好不要對(duì)中斷的入口地址進(jìn)行操作,因?yàn)橄到y(tǒng)已經(jīng)做得很完善了,并提供了了接口函數(shù),如果你對(duì)這個(gè)地址操作不當(dāng)?shù)脑?會(huì)嚴(yán)重影響系統(tǒng),會(huì)破環(huán)整個(gè)系統(tǒng)的中斷響應(yīng).
如果一定要重新寫(xiě)的話,可用memmove()將你的跳轉(zhuǎn)函數(shù)放到0x18處,注意這個(gè)跳轉(zhuǎn)函數(shù)不能大于4個(gè)字節(jié),跳轉(zhuǎn)在C程序中就是簡(jiǎn)單的函數(shù)調(diào)用,和goto是不一樣的. |
Re:Re:Re:Re:Re:Re:請(qǐng)高手指引:EP7312的中斷 |
主題:怎樣實(shí)現(xiàn)在程序中產(chǎn)生一個(gè)系統(tǒng)中斷 |
怎樣實(shí)現(xiàn)在程序中產(chǎn)生一個(gè)系統(tǒng)中斷,比如向串口發(fā)一個(gè)中斷? |
Re:怎樣實(shí)現(xiàn)在程序中產(chǎn)生一個(gè)系統(tǒng)中斷 |
一般中斷的產(chǎn)生是由硬件定義的,如串口中斷的定義:
1.接收中斷:當(dāng)接收中斷使能,接收數(shù)據(jù)存儲(chǔ)器 RxData 存在有效數(shù)據(jù),則產(chǎn)生中斷. 2.發(fā)送中斷:當(dāng)發(fā)送中斷使能,發(fā)送數(shù)據(jù)存儲(chǔ)器 TxData 為空,則產(chǎn)生中斷.
|

硬件發(fā)送中斷產(chǎn)生邏輯示意 |

硬件接收中斷產(chǎn)生邏輯示意 |
所以要產(chǎn)生一個(gè)串口中斷,主要有兩步:
1.使能這兩個(gè)串口中斷,RX Enable,TX Enable,函數(shù)intEnable(). 2.用intConnect()登記中斷號(hào),和相應(yīng)的中斷例程ISR.
只要TX中斷使能,什么都不必做,因?yàn)閿?shù)據(jù)存儲(chǔ)器 TxData 本身為空,就會(huì)有TX中斷產(chǎn)生,自動(dòng)執(zhí)行你的中斷程序.
同樣,RX中斷產(chǎn)生,只要做程序向串口發(fā)送數(shù)據(jù),使RxData中有數(shù)據(jù),也會(huì)產(chǎn)生中斷. |
vxworks也沒(méi)有軟中斷。如果你知道了辦法,請(qǐng)告訴我。 |
為什么不行呢?能否說(shuō)一下你的理由呢? 這里我沒(méi)有用軟中斷,這是用程序來(lái)觸發(fā)串口的硬件中斷呀,RX中斷我曾經(jīng)用過(guò)多次.
VxWorks中好像沒(méi)有實(shí)現(xiàn)軟中斷的函數(shù),一般硬件定義有軟中斷的(Software Interrupt或Program Interrupt),如PowerPC 定義軟中斷向量地址為0x0700,由tw和twi指令來(lái)觸發(fā)中斷.ARM定義軟中斷向量地址為0x8,由SWI指令來(lái)觸發(fā)中斷. 如果想在VxWorks中使用軟中斷的話,可能最好的辦法是在BSP中寫(xiě)一個(gè)匯編程序,然后在其他地方調(diào)用.
我猜測(cè)軟件中斷一般和系統(tǒng)聯(lián)系緊密如系統(tǒng)錯(cuò)誤等等,應(yīng)用層和一般的系統(tǒng)編程基本上用不到,所以VxWorks沒(méi)有提供這樣的函數(shù). |
你的串口硬件中斷的產(chǎn)生我沒(méi)看明白。你是針對(duì)的哪種cpu或是cpu+外圍芯片?860沒(méi)有這樣的機(jī)制。 |
串口硬件中斷的定義應(yīng)該和CPU的種類沒(méi)有關(guān)系,也和cpu或cpu+外圍芯片形式無(wú)關(guān). 我曾用過(guò)IBM PowerPC4xx和ARM7(clps7xxx),這兩種CPU都集成了兩個(gè)內(nèi)部的串口UART,我還在外部擴(kuò)展過(guò)串口芯片ns16552,基本上是一樣的.
MPC860的結(jié)構(gòu)和上面兩種不同,盡管它的核也是PowerPC,它集成了兩個(gè)處理塊,一個(gè)處理塊是嵌入的PowerPC核,另一個(gè)是通信處理模塊(CPM).通信處理模塊有4個(gè)SCC和2個(gè)SMC,這六個(gè)通信口可以通過(guò)設(shè)置來(lái)支持多種協(xié)議和通信方式,也可設(shè)置為串口UART模式(大概是通過(guò)寄存器GSMR或SMCMR),功能和中斷的定義和通常的串口沒(méi)有區(qū)別,你可以查一下寄存器SCCM/SCCE的位14和位15定義,這里定義了在何種情況下產(chǎn)生硬件中斷.
所以MPC860也有這樣的機(jī)制. |
860的cpm我還算熟悉,但我實(shí)在想不出如何能用程序觸發(fā)一個(gè)中斷,即使在看了你的貼子之后。你能不能說(shuō)仔細(xì)些? |
根據(jù)MPC860中SCC UART Event Register(SCCE)的位14和位15定義,如位15是數(shù)據(jù)接收中斷標(biāo)志位,如果串口收到數(shù)據(jù),則產(chǎn)生硬件中斷,所以可以寫(xiě)程序向串口發(fā)數(shù)據(jù),并不是程序產(chǎn)生的的中斷,而是用程序發(fā)送數(shù)據(jù),數(shù)據(jù)到達(dá)串口后,串口有數(shù)據(jù)收到就會(huì)產(chǎn)生RX中斷,通知系統(tǒng)有數(shù)據(jù)到達(dá),有相應(yīng)的中斷例程ISR來(lái)取數(shù)據(jù).
發(fā)送的情況類似,數(shù)據(jù)FIFO為空,產(chǎn)生中斷,告訴系統(tǒng)發(fā)送準(zhǔn)備就緒,可以發(fā)送,ISR把數(shù)據(jù)放入FIFO中,發(fā)送中斷位清零.當(dāng)發(fā)送完畢后,FIFO再為空,再次產(chǎn)生中斷,告訴系統(tǒng)發(fā)送準(zhǔn)備就緒,繼續(xù)發(fā)送.
不知這樣解釋的是否清楚. |
你說(shuō): “所以可以寫(xiě)程序向串口發(fā)數(shù)據(jù),并不是程序產(chǎn)生的的中斷,而是用程序發(fā)送數(shù)據(jù)”。 如何向串口發(fā)送數(shù)據(jù)? |
"如何向串口發(fā)送數(shù)據(jù)?"
這一點(diǎn)主要是實(shí)現(xiàn)的問(wèn)題,和中斷關(guān)系不大
有三種方法實(shí)現(xiàn):
1.一般串口都支持LOOP BACK模式,即片子內(nèi)部自發(fā)自收,設(shè)置成這種模式即可. 2.將串口的發(fā)送腳TX和接收腳TX連接. 3.用PC機(jī)上的Hyper Terminal和串口相連,不用做程序,直接可通過(guò)終端向串口發(fā)數(shù)據(jù). |
ARM 計(jì)時(shí)器中斷編程實(shí)現(xiàn)過(guò)程
ARM7一般內(nèi)部有兩個(gè)16位計(jì)時(shí)器(Timer counter)和一個(gè)32位實(shí)時(shí)時(shí)鐘(RTC),計(jì)時(shí)器中斷屬于IRQ中斷,這里以計(jì)時(shí)器1為例敘述一下中斷的編程過(guò)程
設(shè)置interrup mask INTMR1寄存器 0x80000240 第8位TC1OI計(jì)時(shí)器1為使能. 在0x800000300 計(jì)時(shí)器 1 的數(shù)據(jù)寄存器TC1D寫(xiě)入指定數(shù)據(jù),這樣數(shù)據(jù)開(kāi)始從這個(gè)給定的數(shù)開(kāi)始遞減計(jì)數(shù),計(jì)數(shù)遞減至 0 后,會(huì)產(chǎn)生一個(gè)溢出underflow IRQ中斷請(qǐng)求,中斷狀態(tài)寄存器INTSR1 0x80000240 第8位TC1OI置位.系統(tǒng)會(huì)跳到中斷向量表地址 0x00000018 處,執(zhí)行相應(yīng)的中斷程序,中斷程序通過(guò)判斷中斷的類型(判斷中斷狀態(tài)寄存器的位),來(lái)執(zhí)行相應(yīng)的中斷服務(wù)程序ISR. 中斷狀態(tài)寄存器標(biāo)志位復(fù)位,計(jì)時(shí)器開(kāi)始重新開(kāi)始計(jì)時(shí).
返回頁(yè)首
Intel Flash芯片
參見(jiàn) Flash ROM示例
問(wèn)題 1 :我們現(xiàn)在用的是intel E28F640 J3A120型號(hào)的falsh芯片.在該芯片上要存放配置信 息、某些標(biāo)志位,動(dòng)態(tài)增長(zhǎng),減少的數(shù)據(jù).現(xiàn)在有個(gè)問(wèn)題: 在向某個(gè)地址寫(xiě)數(shù)據(jù)之前,是否一定要擦除該地址所在的塊?
應(yīng)該要擦除該地址所在的塊block,先要Unlock這個(gè)塊,然后擦除該塊,再寫(xiě)操作.通常的操作都是這樣。所以一個(gè)4K--128K塊擦除要用幾百或幾千毫秒,全部Flash擦除用到多達(dá)30秒時(shí)間,很費(fèi)時(shí).這就是為什么現(xiàn)在有些Flash(如ATMEL的AT29C040等)采用較小的block,sector或page(64---512bytes)的原因.
問(wèn)題 2 :(一個(gè)塊是128KBytes,這樣我僅僅為了改寫(xiě)一個(gè)Byte,就必須讀128Kbytes,然后擦除該塊,然后再寫(xiě)128KBytes,太累了,不可能吧??)有沒(méi)有擦除一個(gè)字節(jié)或子的方式?
我想肯定是這樣的,因?yàn)閒lash的命令:Unlock,Erase,Write對(duì)flash的操作都是以塊為單位的,即使你想只擦除一個(gè)字節(jié),實(shí)際上擦除的是一個(gè)塊,即128k.這是flash硬件定義的,對(duì)編程來(lái)說(shuō)并不麻煩,是一樣的,只是花費(fèi)時(shí)間長(zhǎng)一些。沒(méi)有擦除一個(gè)字節(jié)或位的方式。
為了解決以上的問(wèn)題,有些芯片如AT29c040和W29c040采用小的Sector(塊)方式,每個(gè)sector大小只有256bytes,寫(xiě)的時(shí)候,只要打開(kāi)寫(xiě)保護(hù),不需要擦處,直接按sector寫(xiě)入.盡管也要以Sector為單位操作,由于Sector非常小,所以特別適用于修改少量字節(jié)的操作。
問(wèn)題 3 : 我現(xiàn)在要實(shí)現(xiàn)對(duì)INTEL 28F320J3A的操作,但是有一個(gè)很大的問(wèn)題就是我感覺(jué)擦除和寫(xiě)數(shù)據(jù)都比較慢,我想和我沒(méi)有使用它提供的寫(xiě)B(tài)UFFER的命令有關(guān),所以想向您請(qǐng)教寫(xiě)B(tài)UFFER的問(wèn)題.請(qǐng)問(wèn)是不是每一個(gè)大小為128K的塊只有32bytes的buffer,如果我想用寫(xiě)buffer操作,應(yīng)該注意哪些問(wèn)題呢?
對(duì)Flash擦除和寫(xiě)數(shù)據(jù)是慢的,如果用寫(xiě)B(tài)UFFER的命令肯定會(huì)快一點(diǎn),具手冊(cè)上說(shuō),會(huì)快20倍,我沒(méi)試過(guò),不知道.32bytes的buffer不是每個(gè)block都有,是整個(gè)flash只有一個(gè)32bytes的buffer,用寫(xiě)B(tài)UFFER命令對(duì)所有的blocks寫(xiě)操作,都要用同一個(gè)buffer,寫(xiě)B(tài)uffer是主要要檢查buffer是否available,其實(shí)buffer起緩沖作用,來(lái)提高工作效率,
寫(xiě)B(tài)uffer的主要步驟: 1.寫(xiě)write buffer命令到該Block的首地址. 2.先查status,看buffer是否available, 3.寫(xiě)入所寫(xiě)數(shù)據(jù)的的字節(jié)數(shù)到Flash的實(shí)際地址. 4,寫(xiě)數(shù)據(jù) 5.寫(xiě)WRITE_BUFF_CONFIRM命令到該Block的首地址 6.寫(xiě)READ_ARRAY命令到該Block的首地址
其中要注意同一組數(shù)據(jù)跨越不同block時(shí)的處理.
上述步驟是肯定對(duì)的,你可以先試著寫(xiě)出程序,有什么問(wèn)題,我們?cè)俳涣?不要客氣,
問(wèn)題 4 :如果我不使用寫(xiě)buffer的命令操作是不是就會(huì)很慢(寫(xiě)300多K大小的東西要半分多鐘),如果寫(xiě)300多K大小的東西要半分多鐘,我覺(jué)得是不正常的,另外,我對(duì)block erase suspend command和>program suspend command等suspend命令的作用也不是很明白,一下子提了這么多問(wèn)題,希望您沒(méi)看煩,也很希望你能給我一些幫助,先謝過(guò)了
你應(yīng)該檢查一下程序,是不是程序有問(wèn)題,不應(yīng)該這么慢.這些suspend命令,我也沒(méi)有用過(guò),應(yīng)該是在對(duì)一個(gè)block造作過(guò)程中,暫停操作,來(lái)對(duì)另一個(gè)block操作(讀數(shù)據(jù)或執(zhí)行程序),待完成后,再恢復(fù)原來(lái)的.block erase suspend command和program suspend command其實(shí)是一個(gè)命令B0H
返回頁(yè)首
Cillus網(wǎng)卡CS8900A Linux驅(qū)動(dòng)
可參見(jiàn) 網(wǎng)卡示例
Re: 誰(shuí)做過(guò)網(wǎng)絡(luò)接口控制芯片CS8900A的驅(qū)動(dòng)?
我曾經(jīng)寫(xiě)過(guò)這種網(wǎng)卡的驅(qū)動(dòng),它相對(duì)來(lái)說(shuō)比其它的驅(qū)動(dòng)要難一些主要在于EEPROM 和 I/O MODE上,EEPROM 是你必須要操作的,因?yàn)橐话憔W(wǎng)卡的 MAC 地址要侟在這里,另外還有一些用戶設(shè)置。如果你只用網(wǎng)卡默認(rèn)的設(shè)置,可暫時(shí)不用,網(wǎng)卡有兩種運(yùn)行模式,MEMORY MODE 和 I/O MODE,MEMORY MODE 較為簡(jiǎn)單,對(duì)任何寄存器直接操作,不過(guò)你的硬件電路應(yīng)支持才行,主要看有多少地址線和網(wǎng)卡連. 如果采用 I/O MODE 則較為麻煩,對(duì)任何寄存器操作均要通過(guò) I/O PORT 0X300 寫(xiě)入或讀出. 你所做的只是對(duì)一些寄存器進(jìn)行必要的設(shè)置(TX RX ENABLE,IP FILTER,....),然后將莫一地址的數(shù)據(jù)包放入數(shù)據(jù)寄存器即可,無(wú)須考慮 MAC 封包解包的事.
你的問(wèn)題我看了一下,我沒(méi)有在linux下做過(guò)這類程序,不過(guò)我原來(lái)用的操作系統(tǒng) VxWorks是從UNIX移植過(guò)來(lái)的,和linux的環(huán)境相似,用的都是GNU環(huán)境,另外我不清楚或模 糊的地方也查了一些資料.對(duì)你的問(wèn)題回答了一下.大概基本上是正確的.
有什么不清楚的,再來(lái)信,能幫得上你,我很高興.
問(wèn)題 1 :在<<linux設(shè)備驅(qū)動(dòng)程序>>P371:如果一個(gè)驅(qū)動(dòng)程序做為主流Linux核心的一部分發(fā)行的話,它并不聲明自己的device結(jié)構(gòu),而是使用在drivers/net/Space.c中聲明的結(jié)構(gòu)。Space.c聲明了所有網(wǎng)絡(luò)設(shè)備的鏈表,即包括plip1一類驅(qū)動(dòng)程序特定的結(jié)構(gòu),也包括通用目的的eth設(shè)備。以太網(wǎng)根本不關(guān)心它們的device結(jié)構(gòu),因?yàn)樗鼈兪褂猛ㄓ媚康牡慕Y(jié)構(gòu)。這種通用的eth設(shè)備結(jié)構(gòu)聲明ethif_probe為它們的init函數(shù)。程序員要想在主流核心中插入一個(gè)新的以太網(wǎng)接口只需要在ethif_probe中加入一個(gè)對(duì)驅(qū)動(dòng)程序初始化函數(shù)的調(diào)用。另一方面,非eth驅(qū)動(dòng)程序的作者需要在Space.c中插入它們的device結(jié)構(gòu)。在兩種情況下,如果驅(qū)動(dòng)程序必須被鏈到核心,只需要修改源文件Space.c。
在Space.c中: ethif_probe(struct device *dev) { u_long base_addr = dev->base_addr;
if ((base_addr == 0xffe0) || (base_addr == 1)) return 1; /* ENXIO */
if (1 /* All PCI probes are safe, and thus should be first. */ #ifdef CONFIG_DE4X5 /* DEC DE425, DE434, DE435 adapters */ && de4x5_probe(dev) #endif #ifdef CONFIG_UCCS8900 && cs89x0_probe(dev) #endif ................. ................. 這里我想問(wèn)的是,當(dāng)我寫(xiě)完了自己的驅(qū)動(dòng)代碼比如cs89x0.c,cs89x0.h,并在space.c中#define CONFIG_UCCS8900,接 下來(lái)在編譯內(nèi)核的時(shí)候我該去修改哪個(gè)文件,可以將cs89x0.c直接編譯到內(nèi)核中? 如果是按模塊化方式寫(xiě)驅(qū)動(dòng),那么編譯生成.o文件然后insmod一下就可以了;但現(xiàn)在要按非模塊化的方式,直接編譯到內(nèi)核里去,該怎么做呢?
1. 把cs89xx編譯成獨(dú)立模塊,執(zhí)行下列命令: gcc -D_KERNEL_-I/usr/src/linux/include-I/usr/src/linux/net/inet-Wall -Wstrictprototypes -02 -fomit-frame-pointer -DMODULE -DCONFIG_MODVERSIONS -ccs89x0.c 編譯結(jié)果是名為cs89x0.o的驅(qū)動(dòng)程序目標(biāo)模塊。要裝載此驅(qū)動(dòng)程序, 輸入下列命令: insmod cs89x0.o io=0x360 irq=10 //假如網(wǎng)卡的起始端口號(hào)為0x360,中斷號(hào)為10 要卸載此驅(qū)動(dòng)程序,用rmmod命令: rmmod cs89x0.o 2.如果要將驅(qū)動(dòng)程序編進(jìn)系統(tǒng)核心, 修改/usr/src/linux/drivers/net/CONFIG,加入: CS89x0_OPTS= 修改/usr/src/linux/drivers/net/Config.in,加入: tristate‘CS8920 Support’CONFIG_CS8920 以上兩行是為了讓make config在配置過(guò)程中詢問(wèn)是否增加CS89xx網(wǎng)卡的支 持。 修改/usr/src/linux/drivers/net/Makefile加入: ifeq((CONFIG_CS8920),y) L_OBJS+=cs89x0.o endif 修改/usr/src/linux/drivers/net/Space.c,加入: extern int cs89x0_probe(struct device *dev); …… ?。fdef CONFIG_CS8920&& cs89x0_probe(dev); ?。ndif 以上兩段是為了編譯并輸出網(wǎng)卡驅(qū)動(dòng)程序及其例程。 把驅(qū)動(dòng)程序源代碼拷到/usr/src/linux/drivers/net目錄下。 在/usr/src/linux目錄下執(zhí)行 make config或 make menuconfig,選擇核心CS89xx網(wǎng)卡支 持。 執(zhí)行make dep、make clean命令。最后用 make zImage 編譯Linux核心。
問(wèn)題 2 :.uCcs8900.c中的send_test_pkt函數(shù)有什么用呢?其中定義的test_packet數(shù)組 那樣賦值該怎么理解? send_test_pkt(struct device *dev) { int ioaddr = dev->base_addr; char test_packet[] = { 0,1,2,3,4,5,0,3,4,5,6,7, 0, 46, /* A 46 in network order */ 0, 0, /* DSAP=0 & SSAP=0 fields */ 0xf3, 0 /* Control (Test Req + P bit set) */ }; long timenow = jiffies; unsigned short event; writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_TX_ON);
memcpy(test_packet, dev->dev_addr, ETH_ALEN); memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN); outw(TX_AFTER_ALL, ioaddr + TX_CMD_PORT); outw(ETH_ZLEN, ioaddr + TX_LEN_PORT);
/* Test to see if the chip has allocated memory for the packet */ while (jiffies - timenow < 5) if (readreg(dev, PP_BusST) & READY_FOR_TX_NOW) break; if (jiffies - timenow >= 5) return 0; /* this shouldn‘t happen */
/* Write the contents of the packet */ outsw(ioaddr + TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);
if (net_debug > 1) printk("Sending test packet "); /* wait a couple of jiffies for packet to be received */ for (timenow = jiffies; jiffies - timenow < 60; ) ; if (((event = readreg(dev, PP_TxEvent)) & TX_SEND_OK_BITS) ==TX_OK) { if (net_debug > 1) printk("succeeded\n"); return 1; } if (net_debug > 1) printk("failed \n"); return 0; }
這是一個(gè)測(cè)試程序,不僅過(guò)linux操作系統(tǒng)和上層TCP/IP,直接向網(wǎng)卡發(fā)數(shù)據(jù)包,來(lái) 測(cè)試網(wǎng)卡是否工作正常,數(shù)組使用的標(biāo)準(zhǔn)的以太網(wǎng)幀格式(參見(jiàn)相關(guān)的RFC文檔),不用管 它,直接拿來(lái)就用的,這個(gè)數(shù)組的意思是向網(wǎng)絡(luò)個(gè)點(diǎn)發(fā)包,網(wǎng)絡(luò)點(diǎn)收到包好,進(jìn)行回復(fù).
問(wèn)題 3 :我在別的一些cs89x0.c文件中看到這個(gè)函數(shù)是被detect_aui,detect_bnc等這樣 的函數(shù)所調(diào)用,但在uCcs8900.c中的detect_tp中沒(méi)有用到?
BNC基本上現(xiàn)在網(wǎng)絡(luò)都不用了,一般是RJ45的插頭,你可以看一下現(xiàn)在的網(wǎng)卡,沒(méi)有BNC 頭.AUI類似串口通信,盡管現(xiàn)在網(wǎng)卡都支持,但很少用到.所以這里只用了detect_tp()來(lái)檢測(cè)RJ45連線是否存在.
問(wèn)題 4 :這個(gè)函數(shù)里還用到了ETH_ALEN和ETH_ZLEN這兩個(gè)宏,這兩個(gè)宏的解釋我看到過(guò),但 理解的不是很清楚,在這里test_packet,ETH_ALEN和ETH_ZLEN相互間是什么樣的關(guān)系呢?
ETH_ZLEN時(shí)所發(fā)數(shù)據(jù)包的長(zhǎng)度,ETH_ALEN應(yīng)該是6,是MAC地址的字結(jié)數(shù).
問(wèn)題 5 :.驅(qū)動(dòng)編譯到內(nèi)核里,生成映像文件當(dāng)?shù)侥繕?biāo)板上讓系統(tǒng)在目標(biāo)板上運(yùn)行起來(lái)后, 該怎么測(cè)試我的驅(qū)動(dòng)程序呢?需要再寫(xiě)相應(yīng)的測(cè)試代碼嗎?
測(cè)試應(yīng)該是兩步: 1.底層硬件測(cè)試,可用它的send_test_pkt()來(lái)測(cè),或自己寫(xiě)一個(gè)LOOPBACK測(cè)試程序,具體方法可參見(jiàn)CS89手冊(cè),test mode.
2.上層網(wǎng)絡(luò)測(cè)試,可用BSD寫(xiě)一個(gè)網(wǎng)絡(luò)通信程序,開(kāi)發(fā)板和PC及通信傳送大量數(shù)據(jù). 或用linux上FTP服務(wù)來(lái)傳送文件.
問(wèn)題 6 :request_irq(IRQ_MACHSPEC | 20, cs8900_interrupt, IRQ_FLG_STD, "CrystalLAN_cs8900a", NULL)) panic("Unable to attach cs8900 intr\n");
IRQ_MACHSPEC | 20, 該是硬件中斷號(hào),不知道為什么要這樣寫(xiě) IRQ_FLG_STD ,這個(gè)標(biāo)志是要做些什么設(shè)置?中斷共享等等?
IRQ_MACHSPEC | 20中20是硬件中斷號(hào), IRQ_MACHSPEC 應(yīng)該是(0x10000000L),第一位1只是一個(gè)說(shuō)明標(biāo)志,說(shuō)明是特殊設(shè)備中斷. IRQ_FLG_STD是中斷處理的一些屬性設(shè)置,如快速,屏蔽等,我沒(méi)有找到這個(gè)的定義, 可能是標(biāo)準(zhǔn)中斷處理吧.
返回頁(yè)首
LCD 與觸摸屏
我的LCD 分辨率與觸摸屏的分辨率不一樣, 但尺寸相同, 在觸摸屏 上點(diǎn)擊的坐標(biāo)與LCD顯示的坐標(biāo)不一致, 請(qǐng)問(wèn)有什么辦法可 以解決(軟件或硬件解決方案均可)。
環(huán)境: CodeWarrior for 68K, with PPSM |
LCD 分辨率與觸摸屏的分辨率一般來(lái)說(shuō)是不一樣,坐標(biāo)也不一樣,這需要做程序進(jìn)行轉(zhuǎn)換. 我曾做過(guò)這樣的轉(zhuǎn)換,我的LCD分辨率是320*240,坐標(biāo)原點(diǎn)在右下角. 觸摸屏分辨率是900*900,坐標(biāo)原點(diǎn)在左上角. 計(jì)算公式如下: xLCD=320-[320*(x-x2)/(x1-x2)]; yLCD=240-[240*(y-y2)/(y1-y2)];
其實(shí)就是中學(xué)學(xué)的坐標(biāo)轉(zhuǎn)換.這種方法肯定能行的,試試看吧. |
LCD 編程要點(diǎn)
返回頁(yè)首
Modem撥號(hào)
VxWorks下Modem撥號(hào)的主要實(shí)現(xiàn)過(guò)程
這里用到一些串口RS232的定義和AT命令,Modem串口采用ns16552.主要步驟如下
1. off hook,發(fā)出摘機(jī)命令(ATH1\r), 等待modem返回狀態(tài),如果是"OK",則表示成功.進(jìn)行第二步. 2. on hook 發(fā)出掛機(jī)命令(ATH\r), 等待modem返回狀態(tài),如果是"OK",則表示成功.進(jìn)行第三步. 3. off hook,dialing,摘機(jī)撥號(hào)(ATDT....\r), 等待modem返回狀態(tài),如果是"CONNECT",則表示成功.進(jìn)行第四步. 4. send data,發(fā)送數(shù)據(jù).
最好按上述步驟一步一步調(diào),并要等待正確的返回值后再進(jìn)行下一步.
具體程序例子如下,撥號(hào):
// 清空接收FIFO REG(FCR, nsChan) |=FCR_RXCLR; // 等待,直到清空為止 while((REG(FCR, nsChan) & FCR_RXCLR) != 0x00); // 撥號(hào) while(atdt1[i]!=0) { // 檢查發(fā)送FIFO是否準(zhǔn)備好,為空 while((REG(LSR, nsChan) & LSR_THRE) == 0x00); // 在發(fā)送FIFO中放入數(shù)據(jù) REG(THR, nsChan) = atdt1[i]; i++; } // 等待是否有數(shù)據(jù)到達(dá),即modem返回?cái)?shù)據(jù). while((REG(LSR, nsChan) & LSR_DR) == 0x00); // 接收數(shù)據(jù)并判斷返回值 response[i-19]=REG(RBR,nsChan); if(response[0]!=0x43) .................. else .................. // 如果返回值是"connect", while(*data!=0) { while((REG(LSR, nsChan) & LSR_THRE) == 0x00); REG(THR, nsChan) = *data++; } 其他步驟基本一樣.
附: RS232(9 PINS)的主要定義:
Pin 1: DCD (Data Carrier Detect) Pin 2: RXD (Receive) Pin 3: TXD (Transmit)
Pin 4: DTR (Data Terminal Ready) Pin 5: SG (Signal Grund) Pin 6: DSR (Data Set Ready)
Pin 7: RTS (Request To Send) Pin 8: CTS (Clear To Send) Pin 9: RI (Ring Indicator)
其中: DTE for Data Terminal Equipment, such as computer, printer & terminal
DCE for Data Communication Equipment, such as modems.
+3 To +12 volts indicates On or O- state (space)
-3 To -12 volts indicates Off
Usually use swing between +12V~~-12V, dead area between +3V~~-3V
返回頁(yè)首
RTC
怎樣寫(xiě)PowerPc的Real-Time Clock(RTC)的BSP?
PowerPC 內(nèi)部一般只有3個(gè)timer,沒(méi)有內(nèi)部RTC,PowerPC專門(mén)為外部RTC芯片設(shè)置了接口,一般外部RTC芯片是選擇Dallas的,帶有備用電源,通過(guò)SPI進(jìn)行操作,可精確設(shè)置年月日時(shí).... RTC驅(qū)動(dòng)總的來(lái)說(shuō)是不復(fù)雜的,只是要注意一些數(shù)據(jù)格式的轉(zhuǎn)換,如BCD碼等.
RTC一般有SPI接口和標(biāo)準(zhǔn)的三線接口,主要取決于管腳SERMODE,如果SERMODE接Vcc,則為SPI方式。SPI方式用到4個(gè)管腳:SDO,SDI,CE,SCLK.
三線制和SPI方式類似,只不過(guò)是用一個(gè)I/O管腳代替了SDO和SDI.
返回頁(yè)首
PCI驅(qū)動(dòng)
PCI 驅(qū)動(dòng)編程步驟
1。復(fù)制C:\Tornado\target\h\drv\pci目錄下pciAutoConfigLib.h,pciConfigLib.h等PCI頭文件文件和C:\Tornado\target\src\drv\pci目錄下pciAutoConfigLib.c,pciConfigLib.c等PCI文件到BSP目錄下。
2。根據(jù)實(shí)際的PCI硬件定義改寫(xiě)或從寫(xiě)這些PCI文件。
3。改寫(xiě)B(tài)SP配置文件
a. 在BSP 文件config.h中加入語(yǔ)句 #define INCLUDE_PCI (添加PCI模塊)。 b. 在BSP 文件sysLib.c中加入語(yǔ)句 #include "pci/pciConfigLib.c"(主要PCI初始化函數(shù)在這個(gè)文件中)。 c。在BSP 文件sysLib.c中加入語(yǔ)句 IMPORT void sysOutLong(); (導(dǎo)入PCI需要的一些基本函數(shù))。 IMPORT char sysInByte(); IMPORT char sysOutByte(); ...................
返回頁(yè)首
|