vxworks pci驱动
PCI配置空間
當VxWorks內核起來之后,PCI設備的第一次使用都是必須在調用sysHwInit2()例程之后。但是由于MMU內存映射的初始化和激活是在例程sysHwInit()和sysHwInit2()之間的,所以推薦的PCI初始化順序為:
sysHwInit()?默認的MMU?table?entries相當于將本地事務映射為PCI事務的HOST-Bridge的訪問側
sysHwInit2()?在該例程中,程序員必須靜態配置所有的PCI設備,或者調用動態配置routine?pciAutoConfig()
每個PCI設備有3種物理空間:配置空間、存儲器空間和I/O空間。配置空間是長度256字節的一段連續空間(16個32位寄存器)其中前64個字節為頭標,其余192字節為設備相關信息。在64字節的頭標中,前16字節的定義是確定的,后48字節的具體含義因設備而異。配置空間中的一個重要部分是基地址寄存器(BaseAddresssRegister),它的內容是PCI設備的地址空間映射到系統地址空間的起始物理地址。其中,bit0=1表示IO空間映射,bit0=0表示存儲器空間映射。所有PCI設備必須實現存儲器空間映射。通過向BAR寫全1即可確定所需地址空間的大小。在VxWorks下要訪問一個PCI設備,只需要知道該設備的廠商號和設備號。
基于VxWorks的PCi設備驅動程序開發流程,分為4個步驟:①創建設備;②根據PCI設備的配置參數,對PCI設備編寫功能函數程序;
知道廠商號和設備號后,利用VxWorks提供的函數pciFindDevice()獲得設備的總線號、設備編號和功能號。然后調用peiConfigInLong()獲得多功能數據采集卡設備的配置空間、內存空間、I/O空間的地址;pciConfigInByte得到設備中斷號。在讀取設備的基地址時,結合設備相關的說明書進行。
STATUS?pciFindDevice(int?vendorId,?int?deviceId,int?index,int?*pBusNo,int?*pDeviceNo,int?*pFuncNo)
注意第三個參數?‘index’該類PCI設備的索引號,這是在系統中有多個pci設備時我們需要從0開始查找,直到查找到我們想要驅動設備(第一個參數vendorId和第二個參數deviceId相同的設備)。
后面三個參數就是唯一標識該pci設備的資源參數,也是我們在查找pci設備的時候需要獲得該設備空間中的pci設備資源。
由于使用的是PENTIUM系列的CPU來進行板卡驅動的開發,所以在邊接中斷向量的時候,中斷號要加上0x20。
在系統配置PCI設備完畢后,必須首先訪問PCI配置空間獲取相關的信息并傳遞給Device?Driver。因為BIOS在掃描PCI?BUS的過程中,會自動給BUS編號。例如某個設備的編號為(2,5,0)可能會由于通過PCI-PCI橋來擴展或者移除PCI設備而變為(1,5,0)。在正常的設備操作過程中,不應該去訪問PCI的配置空間。
查找到對應的設備之后,需要獲取該設備配置空間的基本資源。
要訪問pci設備空間有專門的訪問控制函數,這里我們使用:
pciConfigInLong():從pci配置空間指定位置讀取一個字長。
pciConfigInLong(int?busNo,int?deviceNo,int?funcNo,int?offset,UINT32?*pData)
注:最后一個參數用于存放返會的數據
通過pciConfigInLong()函數獲取下面的幾個信息:IO地址,PCI設備地址,中斷號。并且需要映射內存,使能I/O
當將PCI設備空間的資源映射出來之后,PCI設備的基本框架就建立起來了。
首先注冊驅動程序,調用:
int?iosDrvInstall()?/?STATUS?iosDevAdd()
Int?iosDrvInstall(FUNCPTR??pCreate,???FUNCPTR??pDelete,FUNCPTR??pOpen,????FUNCPTR??pClose,FUNCPTR??pRead,????FUNCPTR??pWrite,FUNCPTR??pIoctl?)除了最后一個參數之外,其它參數都可以為NULL,最后一個參數向系統注冊一個應用程序與驅動通信的函數。
一般需要進行寄存器的寫入或者讀出,我們會用到下面的函數:
sysInLong(int?port) 用于從寄存器讀出數據,其中的參數為寄存器的地址。?
? ? ? ?sysOutLong(int?port,?long?data)用于向寄存器port中寫入數據data。
但是請注意:sysInLong?(),sysOutLong()函數中的port參數雖然都代表寄存器地址,但不能直接使用芯片手冊提供的地址,需要加一個設備基址“ioaddr”,這個地址是PCI設備空間的io基址。
調用驅動添加函數:
iosDevAdd(&pDrvCtrl?->pFCcardHdr,?name,?drvNum);
其中第一個參數是設備抽象中的第一個參數,也就是內核中的數據結構:DEV_HDR(pDrvCtrl參見前面的文章);第二個參數是我們為設備取的名字,也就是一個字符串;第三個參數為iosDrvInstall()函數的返回值。因此我們需要先調用iosDrvInstall()函數,再調用iosDevAdd函數。
pciConfigLib.c的標準庫給用戶訪問PCI配置空間.
3、PCI?Interrupt?Handling
每個PCI設備都有4個可用的中斷PIN,分別命名為A,B,C和D。每個單功能的PCI設備都被要求使用中斷PIN?A來產生中斷,而對于多功能PCI設備,每個功能使用一個中斷PIN,但是根據PCI規范,每個PCI設備最多可提供8個功能,這樣就必須兩個功能共用一個中斷PIN。當產生PCI中斷時,PCI中斷處理系統需要調用多個中斷服務程序,那么最簡單的方法就是每個ISR都調用一遍,ISR必須有能力判斷該次中斷源是否是自己產生的,如果不是,則立即返回,并接著會調用下一個中斷服務程序。pciIntLib.c提供一些routine來掛接多個ISR到一個中斷LINE上,該庫通過掛接一個特殊的ISR,該ISR會遍歷一個中斷鏈表,所有共用同一個中斷的ISRs都被放在這個鏈表中。pciIntConnect()用于將設備的ISR掛接到中斷鏈表上,而pciIntDisConnect()用于刪除中斷鏈表上的一個ISR。
例子:
pciInitConnect(Vector,?ISR1,?PARAM1);
pciInitConnect(Vector,?ISR2,?PARAM2);
pciInitConnect(Vector,?ISR3,?PARAM3);
上面3個語句把ISR1,ISR2,和ISR3分別掛接到中斷向量為Vector的鏈表intList里面,那么當中斷發生時,會執行下面一個函數:
void?sISR(void)
{
while(intList->next?!=NULL)
(*intList->INT_ISR)(PARAM);/*分別調用ISR1,ISR2,ISR3*/
}
總結
以上是生活随笔為你收集整理的vxworks pci驱动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于javaweb的茶叶商城管理系统(j
- 下一篇: JAVA毕业设计BS架构考研交流学习平台