胡廣浩,阮福明,趙希昉,黃德友,井中武
(中海油田服務股份有限公司 物探事業部,天津 300450)
中國海油開展自主海上高精度地震勘探裝備研發,成功研制出具有自主知識產權的“海亮”高精度拖纜地震采集系統、“海燕”拖纜定位與控制系統(控制系統)、“海途”綜合導航系統、“海源”氣槍震源控制系統,通過多次試驗和生產作業,實現了海洋地震拖纜采集裝備產業化應用,關鍵技術躋身國際先進行列,為實現我國海上油氣增產、保障國家能源安全、建設科技強國做出積極努力。
控制系統是成套地震勘探裝備的重要組成部分,它由船載控制系統和水下控制器組成。它通過控制掛載在拖纜上的羅經鳥的翼板垂直方向移動實現拖纜拖纜沉放深度控制,通過控制水平鳥翼板水平方向移動實現拖纜間距控制,通過控制聲學鳥和水平鳥發射聲學信號進行聲學網絡測距,最后通過實時采集深度數據、航向數據、相對位置數據等,給綜合導航系統提供原始測量數據用于坐標實時解算,最終給地震數據提供位置信息。隨著勘探船拖帶能力提升和拖纜地震勘探向深海發展需要,當前我國勘探船拖帶的拖纜規模達到12(纜)*12 km,每種拖纜上掛載的控制器按照300米間隔布放,控制系統需要在特定的工作周期內完成12(拖纜)*120(控制器)規模的實時控制和數據采集,對數據傳輸的實時性和處理效率要求極高。
VxWorks是一款嵌入式強實時操作系統(RTOS,real-time operating system),以其高可靠、高性能、可剪裁和卓越的實時性被廣泛地應用于通信、軍事、工業控制、航空航天、地震勘探等高精尖技術及實時性要求極高的領域中。緊湊型外設部件互連標準(CPCI,compact peripheral component interconnect)總線具有高開放性、高可靠性、可熱插拔、帶寬高等特點,使其可以廣泛應用在通訊、網絡、實時系統控制(RTMC,real time machine control)、實時數據采集(RTDA,real-time data acquisition)等需要高速運算、高速數據通信、高可靠度、高擴展性的應用領域。本文控制系統的設計既要考慮到實時性和處理效率問題,又要具備一定的擴展性要求,因此采用緊湊CPCI工控機箱作為硬件平臺。CPCI工控機箱的系統槽位運行系統主控板,采用單板計算機和VxWorks實時操作系統軟件平臺,非系統槽位運行定制開發的多通道拖纜控制器接口卡(多通道卡),系統主控板與多通道卡基于CPCI背板總線連接,系統結構如圖1所示。

圖1 控制系統結構框圖
多通道卡由CPCI總線接口芯片和多通道處理電路模塊組成,CPCI總線接口芯片采用BROADCOM公司的PCI9054芯片,多通道處理電路模塊與掛載在拖纜上的水下拖纜控制器通訊,每個多通道處理電路模塊拖帶6個通道。控制系統應用程序運行于系統主控板,多通道卡驅動程序是系統主控板應用程序和多通道卡之間通訊的“橋梁”,它通過對PCI9054接口芯片的控制實現應用程序與多通道處理電路6個通道的數據通訊,從而實現控制系統應用程序對水下拖纜控制器的控制。運行于系統主控板的多通道卡驅動程序和應用程序均運行于VxWorks實時操作系統環境中,多通道卡驅動程序的設計支持多個多通道卡的并發控制,從而為應用程序提供了靈活的擴展能力。
VxWorks采用分層設計和結構化設計,由性能高效的微內核Wind、VxWorks庫、網絡協議棧、I/O系統、文件系統、板級支持包(BSP,board support package)、各類驅動程序等組成。BSP和PCI驅動程序位于硬件與操作系統和應用程序之間,它們在系統中的位置如圖2所示。BSP是一個軟件抽象層,它的主要功能是系統加電以后初始化目標機硬件、初始化操作系統及提供部分硬件的驅動程序,PCI驅動程序是操作系統和應用程序與具體硬件之間的“橋梁”,對上為VxWorks提供標準操作接口和應用程序提供專用接口,對下直接控制硬件設備。對于BSP和PCI驅動程序共同構成了應用程序和具體物理設備的中間層,這種設計思想可以實現應用層軟件與具體物理設備的隔離,提高應用程序的可移植性。本文中系統主控板采用成熟的商用單板計算機,提供了基本的BSP開發包,因此只需要對其進行功能擴展,即可滿足定制的設備。

圖2 板級支持包和驅動程序
外設部件互連標準(PCI,peripheral component interconnect)是由外圍部件互連專業組(PCI-SIG,peripheral component interconnect special interest group)推出的一種局部并行總線標準,PCI總線能夠根據設備上的配置信息自動為設備分配物理地址空間、輸入輸出(I/O,input/output)端口號、中斷號,并且支持多種外部設備。本文CPCI工控機箱采用的背板通信協議是一種基于標準PCI總線的緊湊堅固的高性能總線技術,它定義了更加堅固耐用的PCI版本,在電氣、邏輯和軟件方面,它與PCI標準完全兼容,因此CPCI多通道卡驅動程序的設計完全兼容PCI標準協議。
根據控制系統功能需求,結合VxWorks驅動程序結構和PCI總線特點,將多通道卡驅動程序開發分為內存映射模塊、中斷注冊初始化模塊和中斷處理模塊的設計和實現。
根據PCI規范,每一個PCI總線設備有3種相互獨立的物理地址空間:配置寄存器空間、存儲器空間和I/O空間。其中配置寄存器空間是其容量為256個字節,其中前64個字節為配置頭標區,該區域是固定結構,后192個字節為本地配置空間(設備關聯區),主要定義卡上局部總線的特性、本地空間基地址及范圍等,寄存器布局因設備而異。
配置寄存器空間是PCI設備所特有的一個物理空間,支持設備即插即用,因此PCI設備不占用固定的內存地址空間或I/O地址空間,而是由操作系統決定其映射的基址。配置寄存器空間里最重要的包括廠商標識(Vendor ID)、設備標識(Device ID)、基地址寄存器(BAR,base address register)、中斷號(IRQ Line)、中斷引腳(IRQ Pin)等。配置寄存器空間里基地址寄存器PCIBAR[0-5]反映了該PCI設備的地址空間映射到系統內存空間或I/O空間的起始物理地址。基地址寄存器的最低位bit0是只讀的,其值為1表示該寄存器關聯的地址空間是要映射到I/O空間,否則映射到系統存內存空間的。本文PCIBAR0用于配置本地寄存器、運行時寄存器和DMA寄存器到系統內存空間映射,PCIBAR2用于本地地址空間到系統內存空間映射。基于PCIBAR0的運行時狀態控制寄存器INTCSR用于多通道卡中斷狀態獲取和控制,基于PCIBAR2的寄存器用于多通道數據接口和本地中斷源管理。中斷號的分配由系統在硬件上電階段自動分配,驅動程序只需要獲取到中斷號,通過掛接中斷服務程序即可處理多通道卡觸發的數據請求。主要寄存器設計如表1所示。

表1 主要寄存器定義
基于基地址寄存器PCIBAR2,分別定義6個通道讀寄存器和6個通道寫寄存器用于數據讀取和發送,定義1個中斷源寄存器和1個中斷屏蔽寄存器,分別用于6個通道的中斷標志和屏蔽控制。對于PCI總線設備的配置和控制,VxWorks提供了pciFindDevice()、pciConfigOutLong()、pciIntConnect()等專用應用程序編程接口(API,application programming interface)用于驅動程序開發,下面在具體的實現過程中介紹其使用方法。
VxWorks在BSP的支持下,自動為PCI設備分配4k*16字節大小內存映射空間。VxWorks的內存管理單元(MMU,memory management unit)僅具備基本的內存管理功能,只有將PCI設備的存儲空間加入到MMU中,應用程序才能像操作內存空間一樣操作設備存儲空間。VxWorks中頁大小在的BSP的VM_PAGE_SIZE定義,默認為4k字節,如果需要改變這個值,需要重新重定義config.h中的VM_PAGE_SIZE的值。vmLib.h中的數據結構PHYS_MEM_DESC用于定義映射物理內存的參數,內存映射用sysPhysMemDesc(被聲明為一個PHYS_MEM_DESC的數組)在sysLib.c中定義。在 sysPhysMemDesc中定義的內存區,必須是頁對齊的,并且必須跨越完整的頁,因此PHYS_MEM_DESC 的最初3個域都必須是VM_PAGE_SIZE 的倍數。如果在初始化過程中提供的sysPhysMemDesc的元素不是頁對齊的,則在VxWorks初始化期間將導致系統崩潰。有手動配置和自動配置兩種方式實現MMU對PCI存儲空間的映射,前者在BSP的sysLib.c文件中將設備存儲空間手動添加到內存管理表sysPhysMemDesc中,后者通過sysMmuMapAdd()函數動態將設備的存儲空間地址加入到MMU中。本文基于后者實現方式,通過擴展板級支持包實現內存映射,以獲得更好的靈活性和擴展性,實現過程如圖3所示。

圖3 內存映射模塊流程圖
1)系統硬件初始化入口:在BSP的支持下,VxWorks操作系統初始化過程中,通過調用sysPciAutoConfig()完成系統硬件設備的初始化,主要通過中斷號分配、內存映射空間分配、I/O地址等完成硬件所需資源分配;
2)查找多通道卡:根據設備vendorID(0x10B5)和deviceID(0x9054)采用pciFindDevice()找到對應的設備,獲取到的總線號busNo、設備號deviceNo、功能號FuncNo,總線號busNo、設備號deviceNo、功能號FuncNo組合在一起可以作為該設備的唯一標識;
3)獲取基地址:采用pciConfigInLong()函數獲取設備的寄存器基地址PCIBAR2,獲得的寄存器基地址與存儲器屏蔽位PCI_MEMBASE_MASK邏輯與,得到內存映射基地址;
4)獲取映射空間大小:根據PCI規范,采用pciConfigoutLong()、pciConfigInLong()行數將基地址寄存器全部寫入1再讀回,得到映射空間大小,然后對映射空間進行MMU頁面對齊,確定空間長度;
5)基地址寄存器復位:將mapBaseCsr回寫到基地址寄存器復位,用于后續其他應用需要。
在BSP的sysLib.c中的sysHwInit()函數中擴展內存映射功能,關鍵代碼為:
/* 獲取多通道卡設備的總線號、設備號、功能號 */
if(OK==pciFindDevice(VENDERID,DEVICEID,num,&busNo,&deviceNo,&funcNo)){
/* 獲取PCIBAR2內容 */
pciConfigInLong(busNo,deviceNo,funcNo,PCI_CFG_BASE_ADDRESS_2,&PCIBAR2));
/* 將PCIBAR2全部寫入1 */
pciConfigOutLong(busNo,deviceNo,funcNo,PCI_CFG_BASE_ADDRESS_2,0xffffffff));
/* 再讀回PCIBAR2內容,得到分配內存空間大小 */
pciConfigInLong(busNo,deviceNo,funcNo,PCI_CFG_BASE_ADDRESS_2,&mapSize))
/* 將分配內存空間大小進行4k頁面對齊 */
mapSize=(~(mapSize&PCI_MEMBASE_MASK))+1;
mapSize=ROUND_UP(mapSize,VM_PAGE_SIZE);
pciConfigOutLong(busNo,deviceNo,funcNo,PCI_CFG_BASE_ADDRESS_2,PCIBAR2));
PCIBAR2&=PCI_MEMBASE_MASK;
/* 動態將映射關系加入到MMU */
sysMmuMapAdd((void*)(PCIBAR2),mapSize,VM_STATE_MASK_FOR_ALL,VM_STATE_FOR_PCI);
}
VxWorks啟動過程中,通過板級支持包完成多通道卡存儲空間的MMU管理后,應用程序就可以像操作內存空間一樣操作多通道卡的存儲空間。本文為了提高模塊的獨立性和移植性,將內存映射模塊和中斷注冊初始化模塊進行分離,在中斷注冊初始化過程中,需要再次獲取內存映射基地址,之后中斷服務處理模塊和應用層軟件可以通過操作內存空間的方式對多通道卡的存儲空間進行存取。
VxWorks采用中斷服務表對中斷進行管理,中斷服務表維護了中斷向量和中斷服務程序(ISR,interrupt service routines)的入口地址對應關系。多通道卡有數據到來時采用中斷的方式通知VxWorks系統,以保證數據能得到及時處理,達到實時性要求。為了處理多通道卡產生的中斷,必須獲取其在系統中的中斷號,這個中斷號是VxWorks系統啟動時通過PCI庫進行自動分配。根據PCI9054配置空間定義,我們首先得到的是一個8位的中斷號,這種中斷號需要通過INT_NUM_GET轉換才能得到該設備在VxWorks系統中的中斷號。
獲取到中斷號之后,通過INUM_TO_IVEC轉換成中斷向量,最后將中斷向量和ISR的地址在操作系統的中斷管理模塊中注冊。VxWorks提供intConnect()和pciIntConnect()兩種注冊ISR的方式,intConnect()使用的中斷向量是獨占的,而pciIntConnect()是共享的,即同類型的多個外部設備可以共享同一個中斷向量,它在內部使用一個鏈表管理多個ISR,發生中斷時,鏈接在一個鏈表上的各個ISR被依次調用,pciIntConnect()要求每個ISR被調用時,應該首先查詢是否為自己的設備產生的中斷,不是則應立即返回,以繼續調用其它ISR。控制系統在設計上支持多個多通道卡,因此采用共享中斷向量的方式對多通道卡ISR進行注冊,可獲得更高的擴展性和復用性。完成ISR在VxWorks的中斷系統中注冊后,使能PCI中斷和本地中斷,此后系統就可以處理多通道卡的數據請求。
多通道卡初始化的關鍵代碼為:
/* 獲取多通道卡設備的總線號、設備號、功能號 */
if(OK==pciFindDevice(VENDERID,DEVICEID,num,&busNo,&deviceNo,&funcNo)){
/* 獲取PCIBAR2[num] 內容,用于應用程序訪問 */
pciConfigInLong(busNo,deviceNo,funcNo,PCI_CFG_BASE_ADDRESS_2,&PCIBAR2[num] ));
/* 獲取中斷號 */
pciConfigInByte(busNo,deviceNo,funcNo,PCI_CFG_DEV_INT_LINE,&irqNo))
PCI_DEV[num].irqNo = irqNo;
/* x86架構采用8259A中斷控制器,物理中斷號轉換為系統中斷號 */
intNum = INT_NUM_GET(irqNo);
sysIntDisablePIC(irqNo);
/* 注冊中斷服務程序 */
pciIntConnect(INUM_TO_IVEC(intNum),(VOIDFUNCPTR)pciFastISR,num);
sysIntEnablePIC(irqNo);
/* 獲取中斷控制狀態寄存器 */
PCI9054_Read_PCIBAR0(num,INTCSR,&intCSR); intCSR|= INTCSR_Bit8|INTCSR_Bit11;
/* 使能PCI中斷和本地中斷 */
PCI9054_Write_PCIBAR0(num,INTCSR,intCSR)。
標準的PCI設備驅動程序是VxWorks體系結構中的I/O系統重要組成部分,它通過BSP訪問PCI設備,往上為應用程序提供系統調用入口,從而實現應用層程序與PCI設備的交互。本文采用自定義實現方式,通過跨過I/O系統,采用中斷服務程序和應用層任務的直接通訊,獲得更高的運行效率和實時性。
VxWorks系統的強實時性得益于其獨特的中斷處理模型,快速的硬件中斷處理是其核心的組成部分。為了盡可能快速響應外部中斷,VxWorks的中斷服務程序運行在一個不同于任何任務的獨立的上下文中,中斷處理過程不涉及到任務的上下文切換。操作系統捕獲到中斷后,對注冊到同一個中斷向量的中斷服務程序進行遍歷,通過回調函數完成對相應中斷服務程序的調用。在執行中斷過程中可能會有新的設備中斷到來,為了保證新的更緊急的中斷能得到及時處理,這就要求我們設計的中斷服務程序盡可能的簡短而高效。本文設計如圖4所示處理模型,采用中斷快速處理和中斷處理任務組合的方式完成一次多通道卡數據傳輸請求,中斷快速處理進行數據傳輸請求的中斷快速響應,中斷處理任務進行實際數據傳輸任務。

圖4 中斷處理模塊結構框圖
多通道卡有數據傳輸請求時,產生系統中斷,中斷快速處理由操作系統中斷服務程序自動調用。中斷快速處理運行在操作系統中斷服務的上下文中,是實現整個中斷服務過程的“前半部分”,僅完成必須的工作,包括清除通道中斷標記,給中斷處理任務發出信號量通知,使能通道中斷等,運行極其高效。“前半部分”中斷快速處理關鍵代碼如下:
void pciFastISR(intnum){
UINT32 intCSR;
/* 獲取中斷控制狀態寄存器 */
PCI9054_Read_PCIBAR0(num,INTCSR,&intCSR); if(INTCSR_Bit15 & intCSR){
/* 禁用PCI中斷和本地中斷設備中斷 */
PCI9054_Write_PCIBAR0(num,INTCSR,intCSR&(~(INTCSR_Bit8|INTCSR_Bit11));
/* 釋放信號量,通知上層任務 */
semGive(PCI_DEV[num].semBID);
} }
中斷處理任務實現中斷服務的“后半部分”功能,以高優先級任務的形式由VxWorks進行任務調度,處理相對比較耗時操作,結束后使能下一輪數據傳輸。中斷處理任務啟動后,循環等待中斷快速處理的信號量通知,讀取中斷源寄存器INTMAP,依次遍歷6個標志位判斷中斷源,獲取中斷源后,通過讀取對應的通道接口獲取數據長度和內容,然后將數據放入消息隊列通知應用層軟件,最后使能PCI中斷和本地中斷,通知多通道卡可進行下一輪數據傳輸。“后半部分”中斷處理任務的關鍵代碼如下:
void pciDealTask(int num){
while(1){
/* 等待中斷快速處理的信號量通知 */
semTake(PCI_DEV[num].semBID,WAIT_FOREVER));
UINT32 intMap;
/* 獲取中斷源 */
PCI9054_Read_PCIBAR2(num,INTMAP,&intMap); /* 依次遍歷中斷源標志位 */
for(int chl= 0; chl< 6; ++chl){
if(intMap & (0x01 << channel)){
/*通過 PCI9054_Read_PCIBAR2(num,CHN1R_R + chl*4,&data);執行獲取數據過程,放入消息隊列給上層應用軟件使用,不再詳述 */
} }
/* 使能PCI中斷和本地中斷,使能下一輪數據傳輸 */
PCI9054_Write_PCIBAR0(num,INTCSR,(PCI_INT_BIT|LOCAL_INT_BIT));
} }
驗證文中多通道卡驅動程序,采用模擬測試和實際應用測試相結合的方式。模擬測試通過在主控板軟件編寫模擬程序和多通道卡內部編寫回環程序,驗證2個多通道卡共計12個通道的數據并發讀寫功能正確性和數據處理實時性;實際應用測試通過將驅動程序與主控板應用層軟件進行功能集成,應用到控制系統的生產應用中,驗證驅動程序的可用性。
模擬程序首先完成測試任務初始化,通過pciFindDevice()查找多通道卡,找到后針對每個通道創建測試任務,創建測試任務代碼如下:
taskId_simu[slotNo][channelNo]= taskSpawn(strcat(“simu_”,slotNo<<8|channelNo),200,VX_FP_TASK,0x4000,(FUNCPTR)tSimuTask,slotNo,channelNo,0,0,0,0,0,0,0,0)。
由于每個通道對應一個測試任務,測試任務采用隨機休眠10~20 ms(控制系統與水下羅經鳥、水平鳥、聲學鳥的通訊間隔為約80 ms)的形式模擬多個通道的并發訪問。測試任務通過隨機產生數據,下發至多通道卡所對應通道,接著阻塞在中斷處理服務的消息隊列中,直到有數據返回,將獲得數據后與下發的數據進行比較,實現流程如圖5所示。

圖5 測試程序流程圖
通過對12個通道連續并發測試10萬次,數據傳輸穩定、正確,驗證了驅動程序的正確性和數據處理實時性滿足設計預期。
通過將多通道卡驅動程序與應用層軟件進行功能集成,形成了“海燕”拖纜定位與控制系統。作為中國海油自主海上高精度地震勘探裝備的重要組成部分,控制系統在裝配2個多通道卡情況下,形成了12通道并發處理能力,完成多次實際作業應用,驗證其在拖纜深度控制、間距控制、聲學測距控制等方面均能滿足12條拖纜大規模海上拖纜地震勘探作業對數據傳輸實時性和處理效率的要求。集成多通道卡驅動程序的控制系統在實際生產作業中的成功應用表明,本文設計和實現的多通道卡驅動程序結構合理、功能正確、性能高效,滿足實際野外生產需求,達到了設計的預期。
本文從分析VxWorks實時操作系統驅動程序結構和CPCI總線設備特點入手,依次從VxWorks下內存映射模型、中斷注冊初始化過程和中斷處理過程等方面闡述了VxWorks下CPCI設備驅動程序開發的通用方法,并結合“海燕”拖纜定位與控制系統CPCI多通道卡實例給出了具體過程和關鍵程序代碼。本文實現的CPCI多通道卡驅動程序集成到控制系統中并成功應用于生產作業中,作業效果表明該驅動程序的設計和實現能滿足海上拖纜地震勘探對控制系統的實時性和處理效率要求,達到了設計預期。該驅動程序的設計在不失實時性的前提下,采用了模塊塊化設計、通用性設計,使之能夠靈活的應用到其他具有類似多通道、多任務、實時性要求高的嵌入式系統中。