作者:殷建飛
本文是昨天發(fā)的文章《龍芯杯CPU設(shè)計(jì)競賽與ZYNQ設(shè)計(jì)流程介紹》接續(xù)部分。重點(diǎn)介紹傳統(tǒng)方式的Linux移植和Xilinx的Petalinux的快速移植開發(fā)兩種。
部分硬件設(shè)計(jì)中需要CPU完成對電路寄存器的配置,為了完成Zedboard對FPGA上部分寄存器的配置功能,可以在PS單元(處理器系統(tǒng))上運(yùn)行裸機(jī)程序(無操作系統(tǒng)支持)完成和PL單元(FPGA部分)的數(shù)據(jù)交互功能,此時(shí)PS單元更像單片機(jī)開發(fā);另一種方法是PS單元運(yùn)行Linux操作系統(tǒng),通過驅(qū)動程序和應(yīng)用程序完成對硬件寄存器的讀寫操作,并且Linux有著完整的網(wǎng)絡(luò)協(xié)議棧支持,后續(xù)可拓展性更強(qiáng),可以更好的發(fā)揮ZYNQ這種異構(gòu)架構(gòu)芯片的性能。主要分為兩部分,分別闡述Zedboard中FPGA和處理器互聯(lián)總線與硬件設(shè)計(jì)和Zedboard處理器系統(tǒng)上嵌入式Linux的移植與通過驅(qū)動和應(yīng)用程序簡單配置FPGA寄存器的實(shí)現(xiàn)。上次介紹了沒有操作系統(tǒng)下的驅(qū)動和應(yīng)用程序開發(fā),本文介紹帶操作系統(tǒng)的驅(qū)動和應(yīng)用程序開發(fā)。
1、傳統(tǒng)方式移植Linux
Zedboard上電后會首先啟動BootRom,bootrom中固化了最初啟動需要的初始代碼,并根據(jù)板卡上的跳線決定從flash或者sd卡或者jtag啟動。這里選擇從SD卡啟動,bootrom中的代碼會將SD卡中的啟動文件拷貝到RAM或者片上共享緩存中去,為下一步啟動做準(zhǔn)備。
下一階段的啟動文件負(fù)責(zé)初始化FPGA的比特流文件和初始化ARM處理器的FSBL文件(VIVADO生成),在PL和PS單元完成最基本的初始化操作后,就需要啟動BootLoader來引導(dǎo)后面發(fā)linux內(nèi)核,XIlixn的解決方案中可以將二進(jìn)制比特流文件和fsbl以及uboot打包成BOOT.bin文件,BOOT.bin中的uboot可以加載內(nèi)核到內(nèi)存,并從0x00080000位置啟動內(nèi)核。另外,內(nèi)核啟動還需要設(shè)備樹和根文件系統(tǒng)。
(1)交叉編譯鏈和開發(fā)環(huán)境搭建
為了得到能夠在嵌入式平臺上運(yùn)行的代碼,需要在linux主機(jī)上交叉編譯需要運(yùn)行的代碼,交叉編譯工具鏈就是提供交叉編譯的一套工具集。開發(fā)主機(jī)選擇Ubuntu1604LTS系統(tǒng),安裝VIVADO17.4版本,安裝完成后 VIVADO SDK
用時(shí)已經(jīng)自動安裝了交叉編譯鏈arm-linux-gnueabihf- ,使用命令
source/opt/Xilinx/SDK/2017.4/setting64.sh
添加引用1后即可使用交叉編譯鏈。Xilinx在較早的VIVADO SDK版本中提供了arm-xilinx-linux-gnueabi-編譯鏈,區(qū)別在于arm-linux-gnueabihf-使用硬件加速浮點(diǎn)數(shù)運(yùn)算,而arm-xilinx-linux-gnueabi-使用軟件計(jì)算。通過查詢資料,發(fā)現(xiàn)17.4版本的SDK中包含arm-xilinx-linux-gnueabi-編譯鏈的引用,但是軟件安裝時(shí)沒有成功安裝,這應(yīng)該是17.4版本的一個(gè)BUG,我們在另一臺安裝15.4版本VIVADO SDK的Ubuntu主機(jī)下,找到/opt/Xilinx/SDK/2015/gnu/arm文件夾,將其拷貝到17.4版本對應(yīng)的目錄,發(fā)現(xiàn)可以成功引用,輸入(交叉編譯鏈)gcc-v查看:
gcc版本為4.9.2。需要注意的是,使用兩條編譯鏈中的任意一條都可以用于交叉編譯,但是兩者之前不兼容,因此使用其中一條交叉編譯鏈即可。17.4自帶的gcc編譯器版本更高,是6.2.1版本。
為了支持32 位工具,需要預(yù)先安裝 32 位支持工具包。使用sudo命令獲取root權(quán)限,apt-get install lib32z1 lib32ncurses5lib32bz2-1.0 lib32stdc++6安裝上述工具包。(PS,可以修改Ubuntu鏡像源為西電開源社區(qū)鏡像,實(shí)測速度在5MB左右)。安裝上述包后還需要安裝Openssl庫來實(shí)現(xiàn)網(wǎng)絡(luò)保密性,在編譯u-boot時(shí)會用到,使用命令apt-get install libssl-dev安裝。
為了提高工作效率,嵌入式開發(fā)通??梢栽赪indows下使用SourceInsight等內(nèi)核源碼閱讀工具來開發(fā)驅(qū)動和應(yīng)用程序,而交叉編譯環(huán)境則往往在linux主機(jī)上,因此我們可以使用ssh登陸linux服務(wù)器,完成命令控制和編譯文件,使用ftp文件傳輸服務(wù)在Windows和linux主機(jī)之間傳遞文件,編譯完成的驅(qū)動可以以NFS掛載的方式直接在嵌入式開發(fā)板運(yùn)行。搭建工作環(huán)境不是本文的重點(diǎn),因此不再這里詳細(xì)說明。
(2)U-boot編譯
Xilinx官方提供了u-boot的源碼,位于https://github.com/Xilinx/u-boot-xlnx/releases,我們按照自己需要的版本進(jìn)行下載和使用。
將下載好的u-boot-xlnx-xilinx-v2017.1.zip文件上傳到Ubuntu服務(wù)器,使用命令unzip解壓縮后進(jìn)入u-boot-xlnx-xilinx-v2017.1目錄,在 u-boot 的文件夾下有很多子文件夾構(gòu)成,其中每個(gè)文件夾都實(shí)現(xiàn)一個(gè)對應(yīng)的功能。
1) api:相關(guān)的api函數(shù),如輸出字符函數(shù)。
2) arch: 與特定的 CPU 構(gòu)架相關(guān)。在該目錄下,有u-boot 所支持的各種架構(gòu)的cpu,并且有一個(gè)單獨(dú)的子目錄對應(yīng)。典型的,arch 文件夾下名字為 arm 的子目錄就是 Zynq-7000 SOC所對應(yīng)使用的 CPU 構(gòu)架目錄。
3)board: 和一些已有開發(fā)板有關(guān)的文件。每一個(gè)開發(fā)板都有一個(gè)子目錄出現(xiàn)在當(dāng)前目錄下
4)common: 實(shí)現(xiàn)u-boot 命令行下所支持的命令。在該目錄下,每條命令對應(yīng)一個(gè)獨(dú)立的文件夾。
5)disk: 提供對磁盤的支持。
6)doc:文檔說明
7)drivers: 在該目錄下保存著 u-boot 所支持的設(shè)備驅(qū)勱程序。典型的如各種網(wǎng)卡、支持的CFI 癿 Flash 存儲器、串口和 USB 等。
8)fs:支持的文件系統(tǒng)
9)include:該目錄下保存著 u-boot 所使用的頭文件,對各種硬件平臺支持的匯編文件、系統(tǒng)的配置文件以及對文件系統(tǒng)支持的文件。該目錄下configs 目錄有開發(fā)板相關(guān)的配置頭文件,如 zynq_common.h 是與 zynq 開發(fā)板相關(guān)的配置文件。
10)lib: 該目錄下保存著體系結(jié)構(gòu)相關(guān)的庫文件。
11)net: 該目錄下保存著網(wǎng)絡(luò)協(xié)議相關(guān)的代碼。比如BOOTP 協(xié)議、 TFTP 協(xié)議、RARP 協(xié)議和 NFS 文件系統(tǒng)的實(shí)現(xiàn)
12)tools: 該目錄下保存著用于生成 u-boot 癿工具,包括 mkimage、 crc、 Makefile 和boards.cfg配置文件。
下面開始進(jìn)行u-boot的編譯,編譯u-boot需要扁平化設(shè)備樹的支持,首先輸入命令apt-get installdevice-tree-compiler安裝設(shè)備樹編譯工具。安裝完成dtc工具后就可以進(jìn)行u-boot的編譯了。
在configs文件下保存有各個(gè)開發(fā)板的默認(rèn)配置,我們搜索zynq有關(guān)的配置文件,發(fā)現(xiàn)zynq_zed_defconfig文件,這個(gè)就是Zedboard默認(rèn)的配置選項(xiàng)。而ax70**系列的則是黑金開發(fā)板的默認(rèn)配置文件。
在編譯u-boot之前,需要先將配置選項(xiàng)寫入.config配置文件中,輸入命令make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zynq_zed_defconfig進(jìn)行配置。注意,你需要先source /opt/Xilinx/SDK/2017/setting64.sh添加相關(guān)引用才能使用,當(dāng)然也可以把上述命令寫入/etc/profile這樣就可以開機(jī)使用。
當(dāng)出現(xiàn)written to .configs時(shí),表明配置選項(xiàng)寫入成功,接下來我們就可以進(jìn)行編譯u-boot了。
使用命令make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-編譯u-boot,經(jīng)過一段時(shí)間的編譯后,在u-boot根目錄下會出現(xiàn)u-boot文件,我們將其下載到Windows下并重命名為u-boot.elf,等待下一步使用。
(3)生成BOOT.bin啟動文件
BOOT.bin需要VIVADO SDK生成fsbl,然后將u-boot和VIVADO生成的比特流打包。
啟動VIVADO SDK,選擇File ->New -> Application Project創(chuàng)建一個(gè)新的SDK工程,工程命名為fsbl,其余保持默認(rèn)不變。
點(diǎn)擊next,選擇ZYNQ FSBL模板,點(diǎn)擊Finish完成工程的創(chuàng)建,SDK會自動創(chuàng)建一個(gè)名為fsbl的工程和fsbl_bsp板級支持包。選中fsbl工程,右鍵選項(xiàng)選擇Create Boot Image,在彈出的選項(xiàng)卡中可以發(fā)現(xiàn)SDK已經(jīng)問我們添加了剛才生成的fsbl和有VIVADO導(dǎo)入SDK中的比特流文件,我們只需要再添加編譯好的u-boot即可。
點(diǎn)擊右側(cè)的Add可以添加新的文件,Delete可以刪除選中的文件,Edit可以編輯文件的類型。我們選擇Add添加u-boot.elf文件。
在新的選項(xiàng)卡中填入uboot.elf的路徑,這里一定要注意類型為Datafile類型,否則無法正常啟動。
點(diǎn)擊OK確認(rèn)后退回到上次層選項(xiàng)卡,選擇Create Image選項(xiàng),在SDK目錄下就會生成對應(yīng)的BOOT.bin文件。
將BOOT.bin拷貝到Zedboard的SD卡,連接串口,開機(jī)觀察串口提示,發(fā)現(xiàn)u-boot已經(jīng)可以正常啟動了,并且此時(shí)FPGA也已經(jīng)按照VIVADO的網(wǎng)表文件初始化完成,但是u-boot提示無法讀取內(nèi)核鏡像,我們將在下一步中生成。
(4)內(nèi)核編譯
Xilinx官方提供了linux的源碼,供開發(fā)者下載和使用,我們打開Xilinx官網(wǎng)鏈接:https://github.com/Xilinx/linux-xlnx/releases;選擇17.4版本下載并解壓。
Linux解壓命令為 :
tar zxvf linux-xlnx-xilinx-v2017.4.tar.gz
解壓后進(jìn)入該目錄,這里對關(guān)鍵目錄進(jìn)行說明:
1)include/---- 內(nèi)核頭文件,需要提供給外部模塊使用
2) kernel/---- Linux 內(nèi)核癿核心代碼,包擴(kuò)進(jìn)程調(diào)度子系統(tǒng),以及進(jìn)程調(diào)度相關(guān)的模塊。
3)arch/---- 體系結(jié)構(gòu)相關(guān)的代碼,例如 arm, x86 等等,我們使用的ARM A9處理器就在arch/arm/目錄下。
arch/mach包含了具體開發(fā)板有關(guān)的代碼
arch/boot/dts 包含了設(shè)備樹文件
arch/arm/configs目錄下包含了arm架構(gòu)處理器和開發(fā)板的一些內(nèi)核默認(rèn)配置文件,Zedboard的默認(rèn)配置文件也在此目錄下。
4)driver目錄則存放了可用的驅(qū)動程序,你可以將自己的驅(qū)動放入此目錄,在后面選擇編譯進(jìn)內(nèi)核。
5)scripts目錄下包含了設(shè)備樹編譯器dtc和解釋內(nèi)核配置選項(xiàng)相關(guān)的文件和目錄。
其余目錄則不是本文介紹的重點(diǎn),當(dāng)開發(fā)平臺啟動BootLoader后,需要讀取內(nèi)核鏡像,并依賴設(shè)備樹文件傳入的一些啟動參數(shù)才能啟動。當(dāng)然還需要文件系統(tǒng)的支持。Linux內(nèi)核有Imange、zImage和uImage等格式,Image就是正常編譯出的linux內(nèi)核,但是鑒于嵌入式資源有限,我們可以將內(nèi)核和一段自解壓程序進(jìn)行壓縮,這樣啟動時(shí)BootLoader先調(diào)用zImage的解壓接口進(jìn)行解壓縮,而后在調(diào)用內(nèi)核接口啟動內(nèi)核,相比于Image,zImage啟動更慢一些。uImage就是在頭部加入了一些u-boot相關(guān)代碼的壓縮Linux內(nèi)核鏡像,便于u-boot啟動內(nèi)核鏡像。因此,我們最終要生成的就是uImage內(nèi)核鏡像。
上面說過在arch/arm中存放了我們需要的arm A9處理器的代碼和文件,進(jìn)入arch/arm/configs,搜索zynq相關(guān)的配置,發(fā)現(xiàn)xilinxz_zynq_defconfig配置文件,這就是Zedboard可用的默認(rèn)配置文件。和u-boot類似,我們也需要先寫入默認(rèn)配置到.config文件才能編譯內(nèi)核。
使用命令make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- xilixn_zynq_defconfig進(jìn)行內(nèi)核配置文件的寫入。寫入完成后提示written to .config。可用使用make menuconfig配置內(nèi)核選項(xiàng):
這里保持默認(rèn),無需修改,如果需要將自己的驅(qū)動編譯進(jìn)內(nèi)核,可以在這里選中,但是這樣不利于調(diào)試驅(qū)動。
使用命令make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- 編譯內(nèi)核,內(nèi)核編譯需要較長的時(shí)間。如果配置過程中需要重新修改或者發(fā)生錯(cuò)誤,可以使用make distclean命令使內(nèi)核恢復(fù)最初的狀態(tài),然后重新編譯。
我們使用make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- uImageLOADADDR=0x00008000重新生成內(nèi)核,指定內(nèi)核鏡像為uImage,內(nèi)核入口地址為0x00008000。由于內(nèi)核已經(jīng)編譯過一次,這次可以很快生成。
生成的內(nèi)核位于arch/arm/boot目錄下。拷貝uImage到Zedboard的SD卡準(zhǔn)備啟動時(shí)使用。
(5)生成設(shè)備樹文件
設(shè)備樹是一種設(shè)備節(jié)點(diǎn)的描述,它告訴內(nèi)核板卡上有哪些外設(shè)以及外設(shè)占用的資源,比如寄存器映射空間和中斷號等信息。另外設(shè)備樹還可以修改內(nèi)核啟動參數(shù),如串口選擇、波特率設(shè)置和根文件系統(tǒng)的選擇。
通過VIVADO SDK可以生成設(shè)備樹描述文件,這樣便于我們開發(fā),而不需要完全手動創(chuàng)建。VIVIADO安裝時(shí)并沒有安裝設(shè)備樹生成器,所以需要我們手動安裝。我們首先下載xilinx提供的device tree generator,并安裝到SDK。訪問https://github.com/Xilinx/device-tree-xlnx/releases獲取對應(yīng)版本的設(shè)備樹生成器。下載并放到VIVADO安裝目錄下的SDK/2017.4/data/embeddedsw/devicetree/bsp/目錄下,重命名為device-tree-xlnx_v2017_4(我的VIVADO版本為17.4)。打開SDK,在SDK中操作點(diǎn)擊菜單: Xilinx Tools -> Repositories,然后在LocalRepositories中添加我們剛才下載的SDK/2017.4/data/embeddedsw/devicetree/bsp/device-tree-xlnx_v2017_4路徑并點(diǎn)擊OK。
添加成功后如上圖。點(diǎn)擊菜單File -> New -> Board Support Package。彈出選項(xiàng)卡New Board Support Packet Project,選擇device_tree,如果你上一步配置不成功,則不會出現(xiàn)device_tree選項(xiàng),此時(shí)需要檢查上一個(gè)步驟的問題。添加成功后點(diǎn)擊Finish選項(xiàng),VIVADO SDK會自動生成設(shè)備樹描述文件dts。
稍后,VIVADO彈出BoardSupport Packet Setting選項(xiàng)卡,在bootargs中填入console=ttyPS0,115200 root=/dev/ram rw initrd=0x800000,8Mearlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0。“bootargs”參數(shù)用于指定啟動時(shí)傳遞給內(nèi)核的參數(shù)?!癱onsole device”參數(shù)用于指定所使用的串口輸出設(shè)備。
在SDK目錄下的device_tree目錄下可以看到很多dts文件,system-top.dts就是我們需要編譯的設(shè)備樹描述文件。它引用了zynq-7000.dtsi等對于zynq芯片通用的部分文件。將SDK目錄下的整個(gè)device_tree目錄上傳到Ubuntu服務(wù)器,使用dtc編譯器編譯。編譯命令如下:
./scripts/dtc/dtc-I dts -O dtb -o device.dtb ./device_tree/system-top.dts
6)文件系統(tǒng)
根文件系統(tǒng)使用uramdisk.image.gz根文件系統(tǒng),ramdisk.image.gz根文件系統(tǒng)其格式與uboot不同,啟動時(shí)uboot會提示ramdisk格式錯(cuò)誤,若要讓uboot能夠識別ramdisk.image.gz根文件系統(tǒng),需要利用mkimage給ramdisk.image.gz添加一些頭部信息,生成uramdisk.image.gz??梢灾苯邮褂镁W(wǎng)絡(luò)上的uramdisk.image.gz來作為根文件系統(tǒng),一般來講,根文件系統(tǒng)不需要做出修改。
另一種廣泛應(yīng)用的根文件系統(tǒng)是LINARO_FS,Linaro文件系統(tǒng)也可從網(wǎng)絡(luò)上獲取,因?yàn)槲覀兊脑O(shè)備樹中指定了從uramdisk.image.gz文件系統(tǒng)啟動,因此這里不再介紹從Linaro文件系統(tǒng)啟動。
現(xiàn)在,我們已經(jīng)得到BOOT.bin文件,設(shè)備樹device_tree.dtb文件和根文件系統(tǒng)uramdisk.image.gz根文件系統(tǒng)。將這三個(gè)文件放入Zedboard的SD卡,上電啟動就可以使用Linux操作系統(tǒng)了。
7)驅(qū)動程序和應(yīng)用程序測試
Linux驅(qū)動程序有靜態(tài)編譯進(jìn)內(nèi)核和動態(tài)模塊加載兩種,這里選擇動態(tài)模塊加載的方式,便于進(jìn)行調(diào)試。在前面的硬件設(shè)計(jì)中,我們將AXI-Lite Slave的四個(gè)寄存器掛載到基地址為0x43c00000的位置,而Zedboard板卡上的8位LED燈連接到了寄存器0的低8位,因此我們寫寄存器0的低八位就能很容易的通過LED的狀態(tài)來判斷寫入是否成功。
驅(qū)動程序的入口和出口分別是init和exit,需要使用宏進(jìn)行修飾如下:
// 注冊初始化Linux驅(qū)動的函數(shù)
module_init( leds_drv_init);
// 注冊卸載Linux驅(qū)動的函數(shù)
module_exit( leds_drv_exit);
linux操作系統(tǒng)中無法直接讀寫物理地址,因此入口函數(shù)中,我們需要映射物理地址,使用ioremup函數(shù)映射物理地址。注意這里物理地址和硬件設(shè)計(jì)中保持一致。
leds= ioremap(0x43c00000, sizeof(LEDS_T))
Led燈只是一個(gè)簡單的字符設(shè)備,但是這里我們使用該設(shè)備來注冊設(shè)備驅(qū)動。
ret= misc_register(&misc);
雜項(xiàng)設(shè)備也是在嵌入式系統(tǒng)中用得比較多的一種設(shè)備驅(qū)動。在 Linux 內(nèi)核的include/linux目錄下有Miscdevice.h文件,要把自己定義的misc device從設(shè)備定義在這里。其實(shí)是因?yàn)檫@些字符設(shè)備不符合預(yù)先確定的字符設(shè)備范疇,所有這些設(shè)備采用主編號10,一起歸于misc device,其實(shí)misc_register就是用主標(biāo)號10調(diào)用register_chrdev()的。也就是說,misc設(shè)備其實(shí)也就是特殊的字符設(shè)備,可自動生成設(shè)備節(jié)點(diǎn)。LDD3中l(wèi)ed設(shè)備也是用misc_register函數(shù)注冊為雜設(shè)備,這說明led設(shè)備是作為雜項(xiàng)設(shè)備出現(xiàn)在內(nèi)核中的,在內(nèi)核中,misc雜項(xiàng)設(shè)備驅(qū)動接口是對一些字符設(shè)備的簡單封裝,他們共享一個(gè)主設(shè)備號,有不同的次設(shè)備號,共享一個(gè)open調(diào)用,其他的操作函數(shù)在打開后運(yùn)用linux驅(qū)動程序的方法重載進(jìn)行裝載。
驅(qū)動代碼:
#define DEVICE_NAME "leds"
#define LEDS_BASE_ADDR (0x43c00000)
typedef struct{
volatile unsigned int ADDR0;
volatile unsigned int ADDR1;
volatile unsigned int ADDR2;
volatile unsigned int ADDR3;
}LEDS_ADDR;
LEDS_ADDR* leds;
static int leds_drv_open(struct inode *Inode, struct file *File)
{
leds->ADDR0 = 0xffffffff;
leds->ADDR1 = 0xffffffff;
leds->ADDR2 = 0xffffffff;
leds->ADDR3 = 0xffffffff;
return 0;
}
static ssize_t leds_drv_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
return 0;
}
static ssize_t leds_drv_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
unsigned int ret = 0;
unsigned int tmp_val;
u32 pos = *offset;
ret = copy_from_user(&tmp_val, buf, count);
leds->ADDR0 = tmp_val;
//默認(rèn)寫入寄存器0
return ret;
}
// 描述與設(shè)備文件觸發(fā)的事件對應(yīng)的回調(diào)函數(shù)指針
static struct file_operations dev_fops =
{
.owner = THIS_MODULE,
.open = leds_drv_open,
.read = leds_drv_read,
.write = leds_drv_write,
};
// 描述設(shè)備文件的信息
static struct miscdevice misc =
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops
};
// 初始化Linux驅(qū)動
static int __init leds_drv_init(void)
{
int ret;
leds = ioremap(LEDS_BASE_ADDR, sizeof(LEDS_T));
// 建立設(shè)備文件
ret = misc_register(&misc);
// 輸出日志信息
if(ret)
{
printk("leds_drv_init faiitrt!/n");
}
else
{
printk("leds_drv_init success!/n");
}
return ret;
}
// 卸載Linux驅(qū)動
static void __exit leds_drv_exit(void)
{
iounmap(leds);
// 刪除設(shè)備文件
misc_deregister(&misc);
// 輸出日志信息
printk("leds_drv_exit success!/n");
}
// 注冊初始化Linux驅(qū)動的函數(shù)
module_init( leds_drv_init);
// 注冊卸載Linux驅(qū)動的函數(shù)
module_exit( leds_drv_exit);
MODULE_LICENSE("Dual BSD/GPL");
應(yīng)用程序調(diào)用驅(qū)動程序接口,從控制臺讀取一個(gè)數(shù)字,寫入到寄存器0,寄存器0的低八位就可以在led燈上顯示出來。
應(yīng)用程序源碼:
#include
#include
#include
#include
#include
#include
int main(int argc, char** argv)
{
int fd;
fd = open("/dev/leds", O_RDWR);
if(fd < 0)
{
printf("fd = %d open fialed!/n", fd);
}
//unsigned int leds = 0;
int leds = 0;
char ch[4];
printf("input your strings:/n");
int i = 0;
while( 1 )
{
ch[i] = getchar();
if (ch[i] == '/n')
break;
else
i++;
}
if (i == 3)
{
leds = (ch[0]-48)*100 + (ch[1]-48)*10 + ch[2]-48;
}
if (i == 2)
{
leds = (ch[0]-48)*10 + ch[1]-48;
}
if (i == 1)
{
leds = ch[0]-48;
}
printf("leds = %d,i = %d/n",leds,i);
write(fd, &leds, 8);
printf("end/n");
close(fd);
return 0;
}
將驅(qū)動和應(yīng)用程序上傳到Ubuntu,使用arm-linux-gnueabihf-交叉編譯鏈編譯。驅(qū)動程序需要編寫makefile,Makefile中需要指定一個(gè)已編譯的內(nèi)核源碼樹。編譯完成后再Zedboard板測試如下:
1> 掛載Ubuntu的NFS服務(wù),(需要Ubuntu開啟NFS服務(wù)并指定路徑)首先查詢Ubuntu IP地址為192.168.1.103,在Zedboard控制臺輸入:
mount-t nfs -o nolock 192.168.1.103:/home/zed/work /mnt
將Ubuntu上的work目錄掛載到Zedboard板
掛載成功后使用ssh登陸Ubuntu并轉(zhuǎn)到Ubuntu的驅(qū)動目錄,執(zhí)行make,得到驅(qū)動.ko文件。
Make命令執(zhí)行成功,目錄下生成最終使用的ko文件部分中間文件。使用 arm-linux-gnueabihf-gcc -o ledstest.o ledstest.c 生成測試程序。
回到串口工具連接Zedboard板卡,使用insmod掛載驅(qū)動,并執(zhí)行測試程序。
掛載成功后,運(yùn)行APP成功,APP從控制臺讀入一個(gè)字符串65,將其ASCII碼轉(zhuǎn)換為數(shù)值寫入寄存器0,Zedboard板卡上led如圖:
2、Petalinux快速開發(fā)
Petalinux是xilinx為zynq7000系列移植linux程序設(shè)計(jì)的一套開發(fā)程序。它可以加快嵌入式開發(fā)人員的工作速度。
安裝petalinux首先需要安裝需要的庫,本次實(shí)驗(yàn)在Ubuntu1604LTS上安裝petalinux17.4.注意,petalinux版本和VIVADO版本需要對應(yīng)。
Petalinux無法以root用戶安裝,因此如果想安裝petalinux到非用戶目錄下有兩種辦法:將opt目錄下的文件夾所有屬性改為當(dāng)前用戶或者安裝到當(dāng)前用戶目錄下再以root權(quán)限復(fù)制整個(gè)文件夾到opt目錄。這里選用第一種方法,首先創(chuàng)建安裝目錄:
運(yùn)行petalinux的安裝文件,并指定目錄為/opt/pkg/petalinux,檢查依賴環(huán)境無誤后就會進(jìn)行安裝,安裝前需要根據(jù)提示同意用戶協(xié)議。
安裝完成后就可以使用petalinux定制linux操作系統(tǒng)。Petalinux可以識別VIVADO工程,并根據(jù)VIVADO工程來智能設(shè)置外設(shè)信息。VIVADO工程目錄下的.sdk目錄就包含了petalinux所需的硬件信息。Ubuntu新建文件夾作為petalinux的工程目錄,并將.sdk拷貝到petalinux工程目錄的上一級目錄下,即和petalinux工程目錄為同級目錄。定位petalinux
source/opt/pkg/petalinux/settings.sh
檢查安裝環(huán)境和庫依賴,無問題后可以建立工程。使用命令:
petalinux-create--type project --template zynq –name leds
建立名為leds的工程,cd到leds目錄下,讀取硬件信息:
petalinux-config--get-hw-description ./led.sdk
在彈出的窗口中可以配置petalinux工程,默認(rèn)源碼從GitHub下載,也可以從本地讀取,這里保持默認(rèn)。在 Advanced bootable images storage Settings選項(xiàng)中配置啟動方式,默認(rèn)從SD卡啟動,這里依舊保持默認(rèn)。
將配置保存,退出,petalinux會下載源碼并配置工程。
成功后使用如下命令配置linux內(nèi)核:
petalinux-config-c kernel
配置成功后保存并退出
編譯完成后使用petalinux-config-c rootfs配置根文件系統(tǒng),同樣保存后退出。使用命令petalinux-build編譯整個(gè)系統(tǒng)工程。經(jīng)過一段漫長的等待,編譯完成。
運(yùn)行下面命令生成BOOT文件:
將工程目錄 images -> linux目錄中的BOOT.bin和image.ub復(fù)制到SD卡,啟動Zedboard,完成Linux操作系統(tǒng)的移植。
注意使用petalinux移植linux使用的是arm-linux-gnueabihf-交叉編譯鏈,因此后續(xù)驅(qū)動開發(fā)時(shí)也需要指定交叉編譯鏈為arm-linux-gnueabihf-,后續(xù)驅(qū)動的開發(fā)與傳統(tǒng)方式移植linux部分一致,因此不再闡述。
編輯:hfy
-
Linux
+關(guān)注
關(guān)注
87文章
11232瀏覽量
208950 -
Xilinx
+關(guān)注
關(guān)注
71文章
2164瀏覽量
121039 -
驅(qū)動開發(fā)
+關(guān)注
關(guān)注
0文章
130瀏覽量
12065
發(fā)布評論請先 登錄
相關(guān)推薦
評論