1.1 QNX目標系統(tǒng)嵌入
利用QNX的模塊性和和可裁剪性,其嵌入過程一般是: 構(gòu)建Buildfile -> 編譯buildfile生成系統(tǒng)映象文件 -> 啟動目標系統(tǒng) ->嵌入式系統(tǒng)軟件設計。 其中的關鍵是構(gòu)建Buildfile[19]。通常一個嵌入式系統(tǒng)需要一個可啟動的操作系統(tǒng)映象文件(OS Image)。對于基于QNX的嵌入式一個應用系統(tǒng),就是根據(jù)所選擇的CPU類型以及應用程序所需要的操作系統(tǒng)模塊來定制嵌入式系統(tǒng)。構(gòu)建Buildfile的過程就是配置操作系統(tǒng)映象的過程。簡單來說Buildfile是一個產(chǎn)生映象文件所需遵守的一組規(guī)則、準則。Buildfile由三部分組成,其結(jié)構(gòu)如下: l bootstrap script(啟動引導腳本) l startup script(啟動腳本) l file list(文件列表) 1.1.1 啟動引導腳本(bootstrap script)
不同的CPU其啟動的方式不同,相應的啟動引導程序也就不同。啟動引導腳本bootstrap script的作用就是配置和CPU相適應的微內(nèi)核。一個典型的啟動引導腳本如下: [virtual=x86,bios +compress] .bootstrap = { startup-bios -s 64k -D PATH=/proc/boot procnto } 在這個例子中,第一行說明它是一個啟動引導文件。其中“virtual” 表明該Buildfile將構(gòu)造一個與啟動時產(chǎn)生的虛擬地址空間相對應的啟動映象。關鍵詞“x86,bios” 則分別指處理器(x86)和機器類型(通過bios啟動)。而“+compress”使得映象文件被壓縮,以產(chǎn)生更小的映象文件。startup-bios是運行于具有BIOS的PC兼容系統(tǒng)的可執(zhí)行程序,主要負責利用BIOS檢測PC硬件資源,在這里主要是提取映象,將其置于RAM的相應位置,做基本的配置并運行內(nèi)核。該例中“-s 64k”表明復制ROM中第一段64k視頻BIOS到RAM使其更快的執(zhí)行,即所謂的ROM BIOS映射。第二項參數(shù)表明以57600波特率打開第一個串口作為一個調(diào)試通道,其調(diào)試輸出可以在另一臺通過計算機數(shù)據(jù)傳輸線(null modem cable)連接的PC上捕捉到。最后一項參數(shù)則是實時系統(tǒng)中比較典型的情形,其作用是在任何異常內(nèi)核終止后系統(tǒng)均立即重啟動?!?span lang="EN-GB">PATH=/proc/boot” 確定了PATH環(huán)境變量?!?span lang="EN-GB">procnto” 是微內(nèi)核和進程管理器,包括QNX 6 微內(nèi)核,進程管理,內(nèi)存管理以及路徑名管理,每個利用mkifs工具的可啟動映象都必須具有procnto。需要注意的是在bootstrap中,第一個可執(zhí)行程序必須是startup-*,而最后一個必須是procnto! 1.1.2 啟動腳本(startup script)
啟動腳本是在進程管理啟動后的一系列將要被執(zhí)行的命令列表。一個簡單的script如下: [+script] .script = { devc-con & reopen /dev/con +session] sh } 可以在這里進行配置網(wǎng)絡,設置顯示卡等操作。通常我們自己編寫的需要開機自動執(zhí)行的程序也放在這里,詳細例子見開發(fā)案例。 1.1.3 文件列表(file list)
文件列表是上面的系統(tǒng)程序和用戶程序執(zhí)行所必須的一些文件列表,尤其是一些共享庫。由于用戶程序是用C語言開發(fā)的,所以必須至少包括一個標準C共享庫。例如(“#”后的內(nèi)容為注釋): #include the C shared library libc.so #create a symlink called ldqnx.so.2 to it [type=link] /usr/lib/ldqnx.so.2=/proc/boot/libc.so 其中[type=link]行是用一個ldqnx.so.2重新定位libc.so。如果不知道在映象文件中都是需要哪些共享庫,可以利用“objdump” utility(實用程序)來顯示相關的需求信息。假如我們用到了ping命令,可以在終端執(zhí)行: # objdump -x ‘which ping’ | grep NEEDED 回車,將顯示信息: objdump: /usr/bin/ping: no symbols NEEDED libsocket.so.2 NEEDED libc.so.2 表明ping命令需要libsocket.so.2和libc.so.2,再利用objdump # objdump -x /lib/libsocket.so.2 | grep NEEDED NEEDED libc.so.2 # objdump -x /lib/libc.so.2 | grep NEEDED 即是說libsocket.so.2需要libc.so.2,而libc.so.2不需要任何其他的庫。那么如果包括ping在映象中,就必須在文件列表中列出libsocket.so.2和libc.so.2。 有了Buildfile,我們就可以通過“mkifs”utility生成啟動映象文件,其語法格式是: #mkifs [可選參數(shù)] 源文件 目標文件 比如: #mkifs -v mydoc.build mydoc.ifs 就得到了映象文件mybuild.ifs 啟動映象文件生成后就可以嵌入到目標系統(tǒng),啟動目標系統(tǒng),為進一步的系統(tǒng)開發(fā)做好了準備。詳細的例子見如下開發(fā)案例一。 1.1.4 QNX嵌入案例分析
目標系統(tǒng):pc104的板子,DOC(Diskonchip)存儲器。 設計目標:啟動圖形界面程序,通過網(wǎng)絡實現(xiàn)資源互訪。 1、構(gòu)建Buildfile,我們的mydoc.build如下: [virtual=x86,bios +compress] .bootstrap = { startup-bios –NTarget # 使目標機的名字為Target PATH=/proc/boot:/bin:/sbin:/usr/bin:/usr/sbin:/usr/photon/bin LD_LIBRARY_PATH=/proc/boot:/dev/shmem:/lib:/lib/dll:/usr/lib:/usr/lib/dll procnto } [+script] .script = { devc-con & # 在后臺打開一個控制臺。 reopen /dev/con1 display_msg Welcome to QNX-DOC world ! pci-bios & waitfor /dev/pci devb-doc blk automount=hd0t77:/ & # 后臺運行DOC驅(qū)動程序 #以下設置網(wǎng)絡 io-net -d rtl -ptcpip -pqnet & ifconfig en0 192.168.1.1 # IP地址 route add default 192.168.1.2 #網(wǎng)關IP waitfor /dev/socket # 等待設置 waitfor /bin 15 # 等待調(diào)入其他命令 # 后臺運行其他程序 pipe & mqueue & devc-pty -n 32 & waitfor /sbin waitfor /usr/sbin # 設置環(huán)境變量 SYSNAME=nto TERM=vt100 # 啟動sh reopen /dev/con1 [+session] sh } [type=link] /tmp=/dev/shmem # 設置/tmp為共享內(nèi)存區(qū) [type=link] /usr/lib/ldqnx.so.2=/proc/boot/libc.so # 加入運行時庫 libc.so #標準C庫 libsocket.so # socket 庫 devn-rtl.so # 網(wǎng)卡驅(qū)動 npm-tcpip.so # TCP/IP協(xié)議 npm-qnet.so # Qnet協(xié)議 libcam.so #包含磁盤文件,使我們能夠訪問DOC上的文件 io-blk.so cam-disk.so # 文件系統(tǒng)所需共享庫 fs-qnx4.so devc-con # 控制臺驅(qū)動 devb-doc # DOC驅(qū)動 io-net # 可執(zhí)行文件文件列表 ifconfig pipe mqueue devc-pty pci-bios 2、編譯生成mydoc.ifs 3、做啟動軟盤 把軟盤放進開發(fā)機軟驅(qū),在終端運行: #dinit /dev/fd0 #mount /dev/fd0 /mnt/fd0 #cp /…/mydoc.ifs /mnt/fd0/.boot 這里假設mydoc.ifs在目錄/…/下 4、啟動目標系統(tǒng),格式化DOC #devb-doc & # fdisk /dev/hd0 delete -a # fdisk /dev/hd0 add -s 1 qnx all # fdisk /dev/hd0 boot -s 1 # fdisk /dev/hd0 loaderfds 注意,DOC上所有的原有數(shù)據(jù)都不復存在,需要慎重。 5、重新軟盤啟動目標機,初始化QNX文件系統(tǒng) # dinit -h /dev/hd0t77 # dinit -hb /dev/hd0t77 # mount /dev/hd0t77 / 此時在開發(fā)機上運行“# ls /net”應該可以看到Target和Host(假設開發(fā)機的名字為Host)。 # cp /…/mydoc.ifs /net/Target/.boot 至此,DOC目標機就可以自啟動,而不再依靠軟盤。 1.2 Photon的嵌入過程
在桌面環(huán)境中Photon的運行是通過腳本“ph”實現(xiàn)的[35]。ph腳本主要做如下一些工作: l 啟動Photon服務 l 檢測輸入硬件設備 l 啟動輸入硬件設備驅(qū)動 l 啟動顯卡驅(qū)動,初始化視頻硬件為合適的模式 l 啟動字體管理器 l 啟動windows管理器 l 啟動各個桌面服務程序,比如shelf、桌面背景管理器等。 在嵌入式環(huán)境中,需要手工啟動上述各個服務。這樣做有很多好處,比如可以自己決定系統(tǒng)需要的文件,合理配置自己的嵌入式運行環(huán)境。下面詳細闡述Photon的嵌入過程: 1、設置PHOTON_PATH環(huán)境變量 PHOTON_PATH環(huán)境變量是為了保存Photon安裝的基本目錄。缺省情況下是目錄/usr/photon。該目錄下一般至少存在一下幾個子目錄: l bin:存放Photon的可執(zhí)行程序 l font_repository :Photon的字體以及字體配置文件(OS independent) l palette:圖形調(diào)色板 (OS independent) l translations:Photon 語言翻譯支持 (OS independent) PHOTON_PATH環(huán)境變量的設置可以通過export進行,如下所示: export PHOTON_PATH=/usr/photon 2、啟動Photon服務器 如果不需要給Photon服務進程傳遞任何參數(shù),可以簡單的啟動如下: Photon & 但是,如果嵌入式環(huán)境中有觸摸屏,需要增加Photon的參數(shù)-D,-R,-U等。因為人的手指比一個象素大的多,為阻止觸摸位置的任意變化就需要指定-U選項。需要注意的是Photon必須包含在PATH環(huán)境變量下。在QNX Neutrino中,該位置是/usr/photon/bin??梢酝ㄟ^ export PATH=:/bin:/usr/bin:/usr/photon/bin 來設置PATH環(huán)境變量。 3、啟動輸入設備驅(qū)動 在桌面環(huán)境中,一般通過inputtrap工具來自動搜索輸入設備(鼠標、鍵盤、觸摸屏等)并為其啟動合適的驅(qū)動程序。在嵌入式環(huán)境中,由于存儲空間的限制一般不用inputtrap,因為inputtrap比較大而且嵌入式環(huán)境中輸入設備可能在一個特殊的位置或者不被已存在的devi-*驅(qū)動支持。當然,如果情況允許也可以利用inputtrap,畢竟方便省事的多。手工加載驅(qū)動需要用devi-*系列驅(qū)動,具體見后面的實例。devi-*系列驅(qū)動的位置是/usr/photon/bin。 4、啟動字體管理器 在建立嵌入式系統(tǒng)時要根據(jù)自己的情況決定需要支持什么樣的字體以及是否需要矢量字體等。字體的確定主要有以下幾個方面: l 一般都需要cursor font(phcursor.phf)。 l 如果嵌入式系統(tǒng)中包括了pterm(Photon的一個終端程序),則需PC Terminal(pcterm*.phf),PC Serif(pcs*.phf),或者PC Sanserif (pcss*.phf)字體族。而且需要建立一個$HOME/.photon/pterm.rc文件或$PHOTON_PATH/config/pterm.rc文件來配置終端字體。 l 大多數(shù)基于widget應用程序需要如下幾個定義在fontmap文件里的別名字體: n TextFont n MenuFont n FixedFont n BalloonFont n TitleFont l Web瀏覽器需要如下幾種字體: n Body字體(例如PrimaSans BT、Dutch 801 Rm BT等) n Heading字體(例如Swis721 BT等) n Nonproportional字體(例如Courier10 BT、PrimaSansMono BT等) QNX Photon的字體管理器主要有以下幾種: l phfontphf:只支持Bitmap字體。 l phfontpfr:支持Scalable Bitstream PFR,和TrueType Collection字體。 l phfontFF:支持Scalable TrueType, Type 1, Type 2, Bitstream Speedo (retail encryption),以及Bitstream Stroke等字體。 l phfontFA:支持以上所有字體。 我們要根據(jù)自己所使用字體的實際情況選擇合適的字體管理器。字體管理器的啟動很簡單,如: /usr/photon/bin/phfontphf & 如果啟動映象里沒有包括使用的字體文件,在啟動字體管理器時需要指定包括這些字體文件的路徑,比如: /usr/photon/bin/phfontphf -d /my_dir/font_repository 必須注意的是my_dir必須與$PHOTON_PATH一致。 5、啟動顯卡驅(qū)動 Photon圖形子系統(tǒng)的啟動通過io-graphics實現(xiàn)。例如: io-graphics -g640x480x8 -dldevg-vga.so -P/usr/photon/palette/vga4.pal io-graphics -g1024x768x16 -dldevg-vesabios.so io-graphics -g1024x768x16 -dldevg-rage.so -d0x1002,0x4755 -I0 其中,-g指定圖形的顯示分辨率和顏色深度,-dl指明硬件的驅(qū)動程序,-d指明驅(qū)動唯一確定硬件所需要的PCI制造商以及設備ID,如果有兩個具有相同的制造商和ID的圖形卡的話需要用-I指明是哪塊卡,-P指定使用的palette文件。 這一部分需要的文件主要有: l /usr/photon/bin/io-graphics:啟動圖形子系統(tǒng) l /lib/dll/devg-*:設備驅(qū)動 l /usr/lib/libdisputil.so.2:devg*驅(qū)動使用的庫 l /usr/lib/libffb.so.2:devg*驅(qū)動使用的庫 l /usr/lib/libgui.so:io-graphics使用的庫 l /lib/dll/gri-photon.so:Photon DLL l /usr/lib/libphrender.so:The software rendering routines。 6、啟動windows管理器(可選) QNX Photon Window管理器是pwm(the Photon Window Manager),它提供了標準的窗口管理功能,包括move、resize、minimize、maximize、raise、lower和close。應用程序可以根據(jù)需要定制由pwm提供的標準windows框架。在QNX中,可以通過Ctrl-Alt-Backspace結(jié)束圖形模式回到終端模式。但在嵌入式運行環(huán)境中往往不提倡最終用戶這樣做,我們可以通過pwm來阻止該情況的發(fā)生。例如: /usr/photon/bin/pwm –k 7、啟動自己的GUI程序 如果自己設計的圖形界面程序是一個單個的可執(zhí)行程序且不需要window管理器的話,可以靜態(tài)編譯。如果需要窗口管理器或者有不止一個Photon程序在運行的話最好連接動態(tài)鏈接庫編譯。 只要好好把握以上這七步,很容易就可以定制出優(yōu)異的QNX圖形運行系統(tǒng)。下面修改開發(fā)案例一中的Buildfile,使圖形界面程序可以在目標系統(tǒng)上執(zhí)行。在Buildfile中增加如下部分,重新編譯Buildfile,并把mydoc.ifs復制到目標系統(tǒng)的/ .altboot,重新啟動目標系統(tǒng)。注意啟動時按Esc使系統(tǒng)以altboot啟動。 waitfor /usr/photon Photon & waitfor /dev/photon phfontFA & io-graphics -g800x600x15 -dldevg-geode.so -I0 -d0x100b,0x504 & devi-hirun kbd kbddev ps2 mousedev & #PS/2 鍵盤和鼠標驅(qū)動 myph-program # 執(zhí)行自己的圖形界面程序程序 libm.so.2 # 包含圖形顯示文件 devg-geode.so # 顯卡驅(qū)動 |
|