杜 影1,朱元元,劉康麗1,畢 碩1,谷 靜
(1.北京航天測控技術(shù)有限公司,北京 100041;2.北京航天長征飛行器研究所,北京 100076)
當(dāng)前,鑒于軍工芯片在信息化裝備所處的核心地位,采用自主研發(fā)的國產(chǎn)芯片勢在必行,并且已經(jīng)得到了國家政策的支持和大力發(fā)展。隨著國產(chǎn)核心基礎(chǔ)軟硬件的性能與功能逐步完善,龍芯平臺搭載中標(biāo)麒麟操作系統(tǒng)的模式已成為國產(chǎn)計算開發(fā)平臺的首選,其發(fā)展、推廣和應(yīng)用是國產(chǎn)軟硬件推廣和規(guī)?;l(fā)展的技術(shù)基礎(chǔ)和科學(xué)依據(jù)。
軍用PXI模塊產(chǎn)品一直以地面測試和系統(tǒng)級維修保障為主要任務(wù)。在“自主可控”的背景下,將開源軟件和PXI硬件平臺結(jié)合在一起,打造基于開源軟件的通用PXI測試平臺,建立基于國產(chǎn)龍芯CPU的PXI儀器生態(tài)是實現(xiàn)國產(chǎn)化替代的必經(jīng)之路。如今,PXI產(chǎn)品國產(chǎn)化正面臨著發(fā)展瓶頸與挑戰(zhàn)。首先,在硬件平臺方面,嵌入式控制器的CPU要更換成國產(chǎn)龍芯CPU,其整體性能和穩(wěn)定性有待提高;其次,在軟件開發(fā)環(huán)境方面,龍芯平臺下的儀器控制軟件要摒棄對NI公司LabView、CVI、VISA庫以及WindowsAPI的依賴,而自主開發(fā)“龍芯平臺+中標(biāo)麒麟系統(tǒng)”下的PXI設(shè)備驅(qū)動程序和應(yīng)用程序。
本文將詳細(xì)討論龍芯平臺下PXI設(shè)備驅(qū)動的基本架構(gòu)和設(shè)計方法,并在龍芯平臺下以PXI數(shù)字多用表模塊為例進行試驗驗證。
龍芯3 A系列處理器是首款國產(chǎn)商用四核處理器,文中PXI龍芯平臺所使用的處理器為龍芯3A3000,其工作主頻為1.0 GHz,主要技術(shù)特征為:片內(nèi)集成4個64位的高性能處理器核;8MB的分體共享三級Cache;通過目錄協(xié)議維護多核及I/O DMA訪問的Cache一致性; 2個64位帶ECC,667 MHz的DDR2/3控制器;32位33 MHz PCI; 1個LPC、2 個UART、1個SPI、16路GPIO接口[1]。龍芯3A3000處理器采用MIPS 架構(gòu),因此,目前運行在 X86 架構(gòu)的操作系統(tǒng)與應(yīng)用軟件均無法在龍芯平臺運行和使用,需要通過交叉移植與本地移植的技術(shù)實現(xiàn)軟件環(huán)境適配[2-3]。
國產(chǎn)中標(biāo)麒麟是一種基于Linux內(nèi)核的桌面操作系統(tǒng),支持眾多處理器架構(gòu)。本文使用的PXI龍芯平臺安裝的操作系統(tǒng)為中標(biāo)麒麟桌面操作系統(tǒng)軟件(龍芯版)V5.0,支持龍芯3A3000(64位)平臺采用的 MIPS 架構(gòu),具有強大的網(wǎng)絡(luò)優(yōu)勢和極為突出的安全性和穩(wěn)定[4],支持主流國產(chǎn)軟硬件,能夠最大程度發(fā)揮中標(biāo)麒麟操作系統(tǒng)和龍芯3A3000整機平臺的整體性能。
如圖1所示,本文所搭建的國產(chǎn)龍芯PXI測試平臺包含軟硬件平臺兩個部分。硬件平臺主要由PXI機箱、基于龍芯3A3000處理器的嵌入式控制器和PXI模塊產(chǎn)品組成。軟件平臺主要包括:中標(biāo)麒麟5.0操作系統(tǒng)軟件、集成安裝在該操作系統(tǒng)的可視化軟件開發(fā)工具QT5.6、以及其他腳本語言?;诖似脚_可以完成PXI模塊產(chǎn)品的驅(qū)動設(shè)計、開發(fā)、調(diào)試、加載、調(diào)用,編寫可視化應(yīng)用程序,并進行PXI模塊的功能性能驗證。
在Windows 操作系統(tǒng)下,PXI設(shè)備驅(qū)動開發(fā)人員廣泛采用行業(yè)標(biāo)準(zhǔn)的VISA(虛擬儀器系統(tǒng)I/O接口軟件)對PXI儀器進行配置、控制、編程和調(diào)試,也有小部分開發(fā)人員在WindowsAPI基礎(chǔ)上進一步實現(xiàn)PXI儀器驅(qū)動開發(fā)。但是在國產(chǎn)龍芯平臺搭載中標(biāo)麒麟操作系統(tǒng)的環(huán)境下,以往的PXI設(shè)備驅(qū)動已無法運行和使用(如第1節(jié)所述),程序員必須面向RISC(精簡指令集計算機)體系結(jié)構(gòu)的Linux系統(tǒng)重新開發(fā)PXI設(shè)備驅(qū)動。
考慮到PXI儀器的應(yīng)用場合和測試測量對象,可將PXI設(shè)備驅(qū)動程序?qū)崿F(xiàn)分為以下幾個部分:初始化設(shè)備模塊、設(shè)備打開模塊、數(shù)據(jù)讀寫和控制模塊、中斷處理模塊、設(shè)備釋放模塊和設(shè)備卸載模塊,如圖2所示。
圖2 Linux下PXI設(shè)備驅(qū)動組成部分
初始化設(shè)備需要完成以下工作:
(1)檢查系統(tǒng)(Linux內(nèi)核)是否支持PCI總線;
(2)注冊硬件驅(qū)動程序,即檢查設(shè)備所占用的插槽并保存它所占用的插槽的位置等信息;
(3)啟動PCI設(shè)備,讀取所有配置好的PCI設(shè)備信息中的參數(shù)和屬性(包括廠商ID、設(shè)備ID等)以備驅(qū)動程序使用;
(4)使能DMA(直接數(shù)據(jù)存儲),以便在內(nèi)存操作的時候能夠讓設(shè)備把數(shù)據(jù)通過總線主DMA傳至系統(tǒng)內(nèi)存。
設(shè)備打開模塊主要是根據(jù)當(dāng)前PXI設(shè)備號獲取其設(shè)備參數(shù)和屬性,并申請對當(dāng)前PXI設(shè)備的控制權(quán)。另外,如果當(dāng)前PXI設(shè)備有中斷請求,則需要在該驅(qū)動模塊里申請中斷使能,并在Linux內(nèi)核注冊中斷處理程序。
數(shù)據(jù)讀寫和設(shè)備控制模塊主要通過:讀設(shè)備操作、寫設(shè)備操作、I/O控制操作、內(nèi)存重映射操作等向應(yīng)用程序提供對硬件進行控制的接口。面向不同的PXI設(shè)備驅(qū)動程序,需要程序員重寫該模塊各個接口函數(shù)的方法,從而實現(xiàn)硬件邏輯控制和數(shù)據(jù)的收發(fā)與存儲。數(shù)據(jù)讀寫和設(shè)備控制模塊是整個PXI設(shè)備驅(qū)動程序的核心部分。
中斷處理模塊即指中斷處理程序,當(dāng)系統(tǒng)接收到中斷后,程序先要根據(jù)中斷號判斷是否為當(dāng)前設(shè)備發(fā)出的中斷請求,如符合條件則立即開始執(zhí)行中斷處理程序,例如:在接收到中斷后完成數(shù)據(jù)的接收與存儲或復(fù)位硬件等。而中斷使能如前文所述在設(shè)備打開模塊中完成,中斷釋放則在后面的設(shè)備釋放模塊中完成。
設(shè)備釋放模塊和設(shè)備卸載模塊比較簡單,它們與設(shè)備打開模塊和初始化設(shè)備模塊相對應(yīng),主要是在設(shè)備控制結(jié)束后釋放對設(shè)備的控制以及所占用的內(nèi)存和中斷,并將設(shè)備驅(qū)動程序從內(nèi)核中注銷。
類同于Linux下的PCI驅(qū)動程序,在PXI驅(qū)動程序中起核心作用的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)(struct)也是 pci_driver和pci_dev,它們的聲明包含文件在linux/pci.h中。其中,pci_driver這個數(shù)據(jù)結(jié)構(gòu)涵蓋:設(shè)備模塊名稱、所有能夠驅(qū)動的設(shè)備列表、查找并初始化設(shè)備的函數(shù)和卸載設(shè)備的函數(shù),而pci_dev 這個數(shù)據(jù)結(jié)構(gòu)則詳細(xì)描述了一個PXI設(shè)備幾乎所有的硬件信息,包括廠商ID、設(shè)備ID、各種資源等[5],其數(shù)據(jù)格式在此不做贅述。
在2.1節(jié)的初始化設(shè)備模塊中,啟動PCI設(shè)備后,所有配置好的PCI設(shè)備信息保存在結(jié)構(gòu)體pci_driver中,而在設(shè)備打開模塊中,當(dāng)前PXI設(shè)備的信息保存在pci_dev中。數(shù)據(jù)讀寫和設(shè)備控制是基于pci_dev中的信息執(zhí)行相關(guān)操作的。
在Linux系統(tǒng)下,設(shè)備驅(qū)動程序發(fā)布就是將其編譯成內(nèi)核的一部分,其主要有靜態(tài)編譯和動態(tài)編譯兩種方法:第一種方法要改動內(nèi)核的源文件,直接將驅(qū)動程序編譯成為內(nèi)核的一部分,從而增加了內(nèi)核的大小,且不利于調(diào)試;第二種方法是將驅(qū)動程序編譯成可安裝模塊,通過使用insmod 命令將驅(qū)動程序動態(tài)加載到內(nèi)核中,使之成為系統(tǒng)內(nèi)核的一部分,當(dāng)不使用該設(shè)備驅(qū)動時則使用rmmod 命令將其從內(nèi)核中卸載,另外,還可將加載命令放入開機自啟動選項,這樣,系統(tǒng)開機時就能夠自動加載驅(qū)動。比較兩種驅(qū)動發(fā)布方式,動態(tài)編譯更合理也更靈活[6-7]。
根據(jù)上節(jié)所述,我們首先要在Linux下編寫和加載驅(qū)動模塊文件,即“.ko”文件?!?ko”文件是kernel object文件,其意義在于把內(nèi)核的一些功能移動到內(nèi)核外,需要的時候插入內(nèi)核,不需要時卸載,這樣可以縮小內(nèi)核的存儲容量,而且使用方便。
“.ko”文件的源碼是“.c”文件,該文件的核心內(nèi)容是構(gòu)造驅(qū)動程序的基本框架,文件中含有 2.1節(jié)所述的幾個關(guān)鍵功能模塊以及2.2節(jié)所述的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)。需要注意的是,同加載和卸載模塊相關(guān)的函數(shù)或數(shù)據(jù)結(jié)構(gòu)都要在前面加上__init、__exit等標(biāo)志符,以使同普通函數(shù)區(qū)分開來。
在編譯驅(qū)動文件之前要先編寫Makefile文件,該文件可使用make工具自動完成編譯工作,其有利于程序員修改和重新編譯。Makefile文件的基本內(nèi)容如下(以hello.c生成hello.o為例):
obj-m :=hello.o
KERNEL :=/usr/src/kernels/(uname -r)/
PWD :=(shell pwd)
modules :
(MAKE) -C (KERNEL) M=(PWD) modules
.PHONEY:clean
clean :
rm -f *.o *.ko
在終端執(zhí)行make命令,即在指定路徑下生成了hello.o 文件。然后執(zhí)行insmod命令安裝hello驅(qū)動模塊,如下所示:
insmod hello.ko 相對路徑加載
為了簡化了應(yīng)用層軟件設(shè)計,我們需要進一步生成“.so”(shared object)文件。該文件是Linux下的動態(tài)鏈接庫文件,類似于windows下的.dll 文件?!?so”文件的生成需要“.h”和“.c”文件,為了方便應(yīng)用層軟件的調(diào)用以及不同平臺軟件的移植,我們可以對“.c”文件的函數(shù)進行標(biāo)準(zhǔn)化封裝,函數(shù)名和參數(shù)可依照Windows下dll中的函數(shù)進行定義,例如:
某PXI儀器在Windows下的應(yīng)用程序調(diào)用了visa庫函數(shù)viIn8,那么就可以在Linux下封裝函數(shù)名同為viIn8的函數(shù),并生成相應(yīng)的.so文件提供給Linux下的應(yīng)用程序。這樣,那些使用跨平臺軟件開發(fā)環(huán)境(如Qt)編寫的可視化程序,既不需要更改界面源碼,也不需要更改邏輯源碼,只需要在編譯程序時鏈接“.so”文件,就實現(xiàn)了跨平臺軟件移植。
編譯“.so”文件同樣需要先編寫Makefile文件,其內(nèi)容一般為(以生成libhelloio.so為例):
CFLAGS = -Wall -g -O -fPIC
INCLUDE = helloio.h
TARGET = libhelloio.so
SRCS = helloio.c
OBJS = (patsubst %.c,%.o, (SRCS))
all: helloio
helloio:(OBJS) (INCLUDE)
gcc -shared -fPIC (OBJS) -O3 -o (TARGET)
gcc (CFLAGS) -O3 -c < -o *.o
clean:
rm -f *.o
rm -f *.so
在終端執(zhí)行make命令,即生成了libhelloio.so文件。
目前,龍芯軟件生態(tài)環(huán)境還處于初始發(fā)展階段, PXI儀器軟件的遷移和二次開發(fā)存在一定難度,需要操作系統(tǒng)、應(yīng)用軟件以及硬件兼容的緊密配合。在中標(biāo)麒麟操作系統(tǒng)中可使用的可視化集成開發(fā)環(huán)境是Qt Creator,選擇Qt作為開發(fā)工具不僅因為其開發(fā)功能強大,更主要是因為它有開源版本且支持跨平臺運行[8]。
在Qt Creator中創(chuàng)建工程后除了工程文件本身還包含:頭文件(.h)、源文件(.c)以及界面文件(.ui)。在編寫邏輯代碼調(diào)用“.so”文件時,首先添加相應(yīng)的頭文件,例如helloio.h(對應(yīng)libhelloio.so),然后在工程文件(.pro)中引用庫文件,代碼如下:
LIBS += -L/lib64 -l helloio
如3.1節(jié)所述,如果在驅(qū)動設(shè)計時將.so文件中的函數(shù)封裝為Windows下.dll文件的同名函數(shù),那么在跨平臺移植的過程中,軟件人員不再需要進行二次開發(fā),只需簡單的程序移植并配置好構(gòu)建和運行環(huán)境就能夠編譯出Linux下的可執(zhí)行文件。在Linux下的Qt環(huán)境配置如下圖所示。
圖3 Linux下Qt環(huán)境配置
本文使用的龍芯平臺是試驗版,其中斷服務(wù)功能并不完善,機箱上電后,PXI設(shè)備中斷號在初始化設(shè)備的過程中不能自動分配,也就是說系統(tǒng)不能獲知并列出機箱中所有PXI硬件設(shè)備的中斷號, PXI機箱中每個插槽所使用的硬件設(shè)備中斷號固定(如:1號插槽設(shè)備的中斷號固定為04H),且需要人工測試獲取插槽與中斷號的對應(yīng)關(guān)系。因此,在設(shè)備打開程序中要根據(jù)硬件模塊所在的插槽位置來配置當(dāng)前PXI設(shè)備所對應(yīng)的中斷號,并使能中斷,獲取其使用權(quán)。
這個問題將導(dǎo)致同一型號的PXI硬件設(shè)備無法使用同一個驅(qū)動程序,不同插槽的PXI設(shè)備要根據(jù)其對應(yīng)的中斷號加載不同的驅(qū)動程序,從而影響到同型號PXI模塊驅(qū)動程序的通用性,增加了驅(qū)動開發(fā)的復(fù)雜度。在新版的龍芯平臺上,該問題已解決。
本文將以北京航天測控公司的PXI儀器模塊產(chǎn)品AMC4311(5.5位數(shù)字多用表)為對象,基于龍芯平臺和中標(biāo)麒麟5.0操作系統(tǒng)進行PXI儀器模塊的驅(qū)動程序和應(yīng)用程序開發(fā),以驗證上述Linux下驅(qū)動程序設(shè)計的正確性和實用性。
AMC4311的硬件結(jié)構(gòu)圖如圖4所示,其具備直流電壓、交流電壓、直流電流、交流電流、2線電阻、4線電阻和頻率測量功能[9]。
圖4 數(shù)字多用表模塊硬件結(jié)構(gòu)圖
在龍芯平臺的中標(biāo)麒麟5.0系統(tǒng)下AMC4311驅(qū)動程序開發(fā)過程如下:
(1)編寫設(shè)備驅(qū)動框架函數(shù),形成Amcdev.c源文件;
(2)編寫MakeFile文件,使用make命令生成Amcdev.o文件,生成路徑為:/usr/src/kernels/Amcdev.o;
(3)編寫標(biāo)準(zhǔn)化庫函數(shù),形成amcIO.c源文件和amcIO.h頭文件;
(4)編寫MakeFile文件,使用make命令生成libamcIO.so文件,生成路徑為:/usr/local/lib/libamcIO.so。
可視化軟件開發(fā)環(huán)境選用跨平臺軟件Qt5.6[7],界面源碼和邏輯代碼隔離,這樣可以在不修改界面源碼的情況下,簡單地將Windows下的界面程序移植到Linux下使用;邏輯代碼調(diào)用的驅(qū)動函數(shù)是“l(fā)ibamcIO.so”文件封裝的自定義接口函數(shù)。在Linux下重新配置QT的構(gòu)建和運行環(huán)境,編譯程序生成Linux下的可執(zhí)行文件,其運行界面如下圖5所示。
圖5 龍芯平臺下數(shù)字多用表控制程序運行界面
采用自主可控軟硬件產(chǎn)品對于實現(xiàn)國產(chǎn)化替代、打造自主可控的IT環(huán)境有著非常重要的意義。在全球開源技術(shù)蓬勃發(fā)展,在中國政府力導(dǎo)掌握測量等基礎(chǔ)學(xué)科核心技術(shù)的大背景下,國內(nèi)對包括PXI 在內(nèi)的測試測量技術(shù)一定會更加重視,國產(chǎn)PXI軟硬件產(chǎn)品的市場份額也會保持一個穩(wěn)定上升的增長勢態(tài)。北京航天測控公司已在國內(nèi)率先建立了自主可控的PXI通用測試平臺,軍工科研院所等機構(gòu)也正在通過逆向設(shè)計、自主研發(fā)等方式實現(xiàn)國產(chǎn)化替代。未來,龍芯平臺搭載中標(biāo)麒麟操作系統(tǒng)的軟硬件組合將為我國自主軟硬件產(chǎn)業(yè)帶來良好的發(fā)展機遇。