RK3288 Linux Manual
QT5.1移植
編譯uboot、kernel
說明:QT系統使用的uboot與內核是與安卓一套代碼,所以需要使用到安卓的代碼包,為防止混淆,特此說明。與安卓的區別是,boot.img使用busybox生成,system.img使用buildroot生成。
為適配QT環境的LCD與觸控螢幕需要配置兩個宏,
修改kernel/drivers/input/touchscreen/gslX680.c文件: 如果是qt, 需要#define TS_QT 如果是android , 需要 //#define TS_QT 修改kernel/drivers/video/rockchip/lcdc/rk3288_lcdc.c文件: 如果是qt, 需要#define LCD_QT 如果是android , 需要 //#define LCD_QT
配置完上述兩個宏後,接下來根據《x3288 android平台用戶手冊》將安卓代碼編譯一遍,下面講如何生成QT的文件系統。
註:目前代碼配置稍顯麻煩,後續我們會整理代碼,使編譯使用更方便。
安裝busybox生成boot.img
從網盤下載busybox-1.19.4.tar.gz拷貝到用戶目錄,執行下面指令解壓縮:
tar -xvf busybox-1.19.4.tar.gz
cd busybox-1.19.4
打開makefile,配置交叉編譯工具鏈路徑,筆者路徑如下:
CROSS_COMPILE ?= /usr/local/opt/ARM/toolschain/4.4.3/bin/arm-linux-
用戶可根據自己的交叉編譯鏈路徑進行配置,配置完後執行
make
make install
dd if=/dev/zero of=initrd.img bs=1k count=8192
sudo mkfs.ext2 -F initrd.img
sudo mkdir /mnt/initrd
sudo mount -t ext2 -o loop initrd.img /mnt/initrd
sudo cp _install/* /mnt/initrd -a
sudo umount /mnt/initrd
gzip --best -c initrd.img > ramdisk.img
sudo chmod 777 ramdisk.img
Androidpath:rkst/mkkrnlimg ramdisk.img boot.img >/dev/null
根目錄即生成boot.img。
註:androidpath是指安卓代碼的路徑,mkkrnlimg工具在安卓代碼中,用戶可以將上述代碼編寫成一個腳本方便編譯。
安裝、編譯buildroot源碼包
從光碟中拷貝buildroot源碼包buildroot-x3288.tar.gz,拷貝到ubuntu的home目錄,使用命令終端解壓buildroot-x3288.tar.gz到當前目錄,即完成了buildroot安裝,如下圖所示:
tar -xvf buildroot-x3288.tar.gz
cd buildroot-x3288
make
cp output/images/rootfs.ext2 ./system.img
QT環境下的system.img製作完成。
編譯文件系統
在buildroot目錄下執行make指令即可編譯文件系統。默認編譯會少一些插件或庫,會彈出一些錯誤信息。
該提示信息表明編譯需要git包,執行如下指令安裝:
sudo apt-get install git
該提示表明標準的C++庫沒有安裝,執行如下指令安裝:
sudo apt-get install lib32stdc++-4.9-dev
該提示表明缺少libz庫,執行如下指令安裝:
sudo apt-get install lib32z1
再執行make指令即可正常編譯了。編譯完成後,最終打包好的文件系統rootfs.ext2存放在buildroot\output\images目錄下。rootfs.ext2文件系統默認並不是ext2格式,而是ext4格式。同時,它裡面包含了QT5.1的標準庫,以及一些常用的QT示例,在後續章節我們將會詳細描述。
燒寫linux QT映像
ubuntu下fastboot的安裝
安裝fastboot
執行如下指令安裝fastboot:
sudo apt-get install android-tools-fastboot
新建51-android.rules
新建51-android.rules文件,內容如下:
# adb protocol on passion (Nexus One) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e12", MODE="0666", OWNER="lqm" # adb protocol on crespo/crespo4g (Nexus S) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e22", MODE="0666", OWNER="lqm" # fastboot protocol on crespo/crespo4g (Nexus S) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e20", MODE="0666", OWNER="lqm" # fastboot protocol on stingray/wingray (Xoom) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="708c", MODE="0666", OWNER="lqm" # fastboot protocol on maguro/toro (Galaxy Nexus) SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e30", MODE="0666", OWNER="lqm" # fastboot protocol on x210/x4412/x4418 SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="0002", MODE="0666", OWNER="lqm"
注意,OWNER裡面填的」lqm」務必換成自己ubuntu系統的用戶名。之后将51-android.rules文件複製到/etc/udev/rules.d/ 目錄下。
到此,就可以使用fastboot更新映像了。如果不建51-android.rules這個文件,使用fastboot更新時需要使用root權限。
Windows下燒寫映像文件
生成update.img
需要用到的工具是qt_rockdev(不是rktools下的rockdev,主要是參數配置做了更改,具體的用戶可以自行對比)將剛剛編譯生成的system.img與boot.img拷貝到qt_rockdev\Image目錄下,再將安卓代碼生成的kernel.img、misc.img、pcba_small_misc.img、pcba_whole_misc.img、recovery.img、resource.img也拷貝到qt_rockdev\Image目錄下。
接著拷貝bootloader到qt_rockdev目錄下,並重命名成RK3288UbootLoader_V2.19.09.bin(之所以重命名,是為了與package-file中一致,如果不喜歡可以修改package-file即可);最後雙擊運行mkupdate.bat生成update.img:
燒錄固件update.img
打開
RKTools\windows\AndroidTool_Release_v2.3\AndroidTool_Release_v2.3\AndroidTool.exe,
選擇「升級固件」選項卡,點擊「固件」,在彈出窗口中選擇已經生成的update.img 文件,如下圖所示。
工具配置好後,連接開發板(如下圖):
按下RECOVERY鍵,然後插上microUSB線與5V DC電源線:
燒錄工具界面會提示發現一個LOADER設備,然後點擊升級,即可開始升級過程(註:如果提示發現一個ADB設備,點擊切換按鈕切換成LOADER設備即可)。
上圖為升級完成截圖。
多設備升級固件update.img
打開路徑:
SDK\RKTools\windows\FactoryTool_v1.33下的“FactoryTool.exe”,
點擊「固件」選擇update.img,勾選「升級」,點擊「啟動」,如下圖所示:
步驟1 點擊固件,選擇update.img;
步驟2 點擊啟動(選擇升級按鈕);
步驟3 連接開發板USB、DC電源,按下recovery鍵,對應USB口發現設備,並實現自動升級;然後重複步驟3即可同時升級第二台、第三台設備,升級成功或者失敗的設備會在兩邊的列表中列出,移除成功或者失敗的設備後可以繼續連接需要升級的設備。
ubuntu下燒寫映像文件
註:linux系統下無需安裝驅動。
解壓RKTools工具包,將RKTools\linux\Linux_Upgrade_Tool_v1.2\rockdev工具拷貝到用戶目錄;
拷貝映像文件 kernel.img、resource.img、misc.img、boot.img、recovery.img、system.img 放入 rockdev\Image 目錄中;
拷貝xxxx_bootloader.bin和xxxx.parameter.txt文件到rockdev目錄,並將其分別重命名為RK3288Loader_uboot_Apr212014_134842.bin和parameter。
註:之所以要重命名是因為mkupdate腳本中定義的名稱,如果用戶不喜歡修改文件名可以自行修改mkupdata中的文件名即可。
配置packge-file:
# NAME Relative path # #HWDEF HWDEF package-file package-file bootloader RK3288Loader_uboot_Apr212014_134842.bin parameter parameter misc Image/misc.img kernel Image/kernel.img resource Image/resource.img boot Image/boot.img recovery Image/recovery.img system Image/system.img # 要写入backup分区的文件就是自身(update.img) # SELF 是关键字,表示升级文件(update.img)自身 # 在生成升级文件时,不加入SELF文件的内容,但在头部信息中有记录 # 在解包升级文件时,不解包SELF文件的内容。 # RESERVED不打包backup backup RESERVED update-script update-script recover-script recover-script
配置完成後在執行mkupdate.sh生成update.img
work@ubuntu:~/3288/Linux_Upgrade_Tool_v1.2/rockdev$ ./mkupdate.sh
如下圖所示為成功界面,在rockdev目錄下生成update.img:
燒錄固件update.img
工具路徑:RKTools\linux\Linux_Upgrade_Tool_v1.2
在升級之前將update.img拷貝到upgrade_tool相同目錄下,運行upgrade_tool(需要sudo)
work@ubuntu:~/3288/Linux_Upgrade_Tool_v1.2/cp rockdev/update.img .
work@ubuntu:~/3288/Linux_Upgrade_Tool_v1.2$ sudo ./upgrade_tool
執行結果如下圖,發現設備列表,輸入要升級的DevNo(設備號)選擇設備:
選擇設備後彈出工具使用菜單如下圖,左側是功能描述,右側是命令語法,升級相關操作都在upgrade command列表下,忘記命令語法可以輸入H進行查看,清屏輸入CS,退出按Q。
- CD命令: 選擇設備, 當執行的命令有包含設備重啟操作時, 需重新選擇設備,當改變操作設備時需重新選擇
- SD命令:msc切換到rockusb升級模式。 當切換執行成功後, 需要重新選擇設備
- UF命令:升級完整update.img固件,當執行成功後需要重新選擇設備
- UL命令:升級loader功能,當執行成功後需要重新選擇設備
- DI命令:下載單獨image鏡像到指定扇區,例如升級kernel.img或者system.img都可以直接使用此功能.例如下載kernel.img: DI -k kernel.img parameter //如果之前通過DI下載過parameter,則再下載kernel.img時就可以不用指定最後的parameter參數
- DB命令:下載boot,在maskrom狀態下,可以通過此功能, 讓maskrom設備進行Rockusb協議通訊
- EF命令:擦除整個nandflash
- LF命令:低格保留塊後面區域,只有在loader模式下使用
執行uf update.img開始更新固件,下圖為更新完成截圖。
Rockusb>uf update.img
備註:也可通過配置config.ini文件配置升級映像文件,只需輸入UF即可升級,請用戶自行嘗試。
Rkflashkit
rkflashkit 有圖形界面,後加了命令行支持,更是好用。
work@ubuntu:~/rktool$ sudo apt-get install build-essential fakeroot work@ubuntu:~/rktool$ git clone https://github.com/linuxerwang/rkflashkit work@ubuntu:~/rktool$ cd rkflashkit work@ubuntu:~/rktool$ ./waf debian work@ubuntu:~/rktool$ sudo apt-get install python-gtk2 work@ubuntu:~/rktool$ sudo dpkg -i rkflashkit_0.1.4_all.deb
注意:rkflashkit_0.1.4_all.deb會因版本更新,版本數字可能會有所變化,如果執行失敗,執行ls命令查看下即可。
work@ubuntu:~/rktool/$ sudo rkflashkit
如下是圖形界面,在Devices下選擇設備,選擇要燒寫的分區和對應的映像文件,點擊Flash image即可。
該工具也支持命令行,使用help命令查看使用方法
work@ubuntu:~/rktool/rkflashkit$ rkflashkit --help Usage: <cmd> [args] [<cmd> [args]...] part List partition flash @<PARTITION> <IMAGE FILE> Flash partition with image file cmp @<PARTITION> <IMAGE FILE> Compare partition with image file backup @<PARTITION> <IMAGE FILE> Backup partition to image file erase @<PARTITION> Erase partition reboot Reboot device For example, flash device with boot.img and kernel.img, then reboot: sudo rkflashkit flash @boot boot.img @kernel.img kernel.img reboot work@ubuntu:~/rktool/rkflashkit$
使用TF卡升級固件
功能說明
SD Card Boot 功能是主控在上電時,優先從 SD 卡上查找啟動代碼,然後加載引導,從而實現特定功能。目前 SD Card Boot 已經實現兩個功能:SD 卡升級和 SD 卡運行。
SD 卡升級功能,將 SD 卡啟動代碼寫到 SD 卡的保留區,然後將固件拷貝到 SD 卡可見分區上,主控從 SD 卡啟動時,SD 卡啟動代碼和升級代碼將固件升級到本地主存儲中,並支持PCBA 測試和 Demo 文件的拷貝。可以完全做到脫離 PC 機進行固件升級,提高生產效率。
SD 卡運行功能,將固件升級到 SD 卡保留區中,把 SD 卡當作主存儲使用。主控從 SD 卡啟動時,固件已經存放在 SD 卡上,有沒有本地主存儲都可以正常工作。目前主要應用是板卡廠做 PCBA 測試,而不會破壞 flash 數據。
軟體說明
工具目錄有如下文件:
SD_Firmware_Tool.exe:制卡工具
Config.ini:配置文件
SDBoot.bin:SDRK2926、RK2928、RK3166 和 RK3188使用 SDBoot.bin 支持 SD 卡升級和啟動功能;RK3288使用RK3288Loader_uboot_V2.16.bin 及以後版本。
製作前軟體配置
編輯config.ini配置文件以下項目設置為TRUE
- #當值為TRUE時,新卡格式適用3288項目
- USE_FW_LOADER=TRUE
工具界面如下:
製作
注意:製作啟動卡會格式化SD卡,用戶需要注意備份重要數據,防止誤刪。
第一步,選擇對應的可移動磁碟設備;
第二步,選擇功能模式:固件升級、PCBA測試、SD啟動;
- 默認會勾選「固件升級」,即只升級固件。
- 如果在升級固件前需要做 「PCBA 測試」,則同時勾選「固件升級」、「PCBA測試」。
- 如果不升級固件,只需要測試PCBA,則單選「PCBA測試」,不選擇「固件升級」。
- 「SD啟動」會把固件燒寫到 SD 中,所有分區都分配在 SD 卡上,運行時不會修改內部存儲的數據(相當於 SD 卡做主存儲設備)。
注意:SD卡運行模式,對kernel的編譯有要求,需要把kernel的SD卡驅動配置去掉,不參與編譯。
修改為:
第三步,選擇對應平台的update.img固件;
第四步(可選),如果需要拷貝 demo 文件到用戶盤根目錄,點擊選擇Demo按鈕,選擇需要拷貝的文件目錄。選擇的目錄下所有文件會拷貝到 SD 根目錄下的 Demo 目錄中,在 SD 引導固件升級後,Demo 目錄下的文件會拷貝到樣機用戶盤的根目錄下。
第五步,點擊開始創建即可。
恢復卡
將製作成啟動卡的SD卡恢復為普通SD卡。
QT文件系統的搭建
前面章節的介紹,都是九鼎創展工程師已經移植的文件系統包,如果換一個平台,一切從零開始,我們如何構建linux QT文件系統呢?本章節將會帶您一步步搭建linux文件系統。
下載buildroot
在buildroot官網下載最新的buildroot包,下載地址如下:
http://buildroot.uclibc.org/download.html
通常我們選擇最新版本的下載即可。
配置buildroot
將下載的buildroot包拷貝到ubuntu系統用戶目錄並解壓,得到buildroot目錄,通過命令終端進入buildroot目錄,執行make menuconfig,進入配置界面:
進入Target options菜單,
在Target Architecture中選擇ARM(little endian),在Target Binary Format中選擇ELF,Target Architecture Variant中選擇cortex-A9,Target ABI選擇EABIhf,Floating point strategy選擇VFPv3-D16,ARM instruction set選擇ARM。
退回上一級,進入Toolchain目錄,按下圖配置:
退回上一級,進入System configuration目錄,作如下配置:
退回上一級,進入Target packages目錄,再進入Graphic libraries and applications (graphic/text)目錄,選擇Qt5,如下圖所示:
注意不要選Qt,它對應QT4.8版本。進入Qt5菜單,按下圖配置:
退回menuconfig的開始界面,進入Filesystem images菜單,作如下配置:
到此,buildroot配置完成。默認配置保存在buildroot根目錄的.config中,我們可以備份該配置文件,以防後續配置出錯。執行如下指令備份配置文件:
cp .config x4418_config
編譯buildroot
配置完成後,執行make指令即可編譯buildroot了。編譯buildroot會會依賴一些第三方插件和庫,在QT5.4移植章節的編譯文件系統小節中,已經給出了需要安裝的包,在編譯之前需要提前安裝,否則會報錯。 編譯完成後,文件系統映像rootfs.ext2會生成到output/images目錄。
測試QT5.1默認示例
將uboot,內核,文件系統燒寫進開發板,進入linux文件系統後,可以進入/usr/lib/qt/examples目錄測試QT示例。
進入gui/analogclock目錄,執行analogclock文件,指令如下:
./analogclock &
這時,在開發板上可以看到有一個時鐘圖案被繪製出來(會覆蓋默認的QTTEST程序),如下圖所示:
進入gui/rasterwindow目錄,執行rasterwindow文件,指令如下:
./ rasterwindow &
這時,在開發板上可以看到一個標註有QWindow的圖案被繪製出來,如下圖所示:
進入qpa/windows目錄,執行windows文件,指令如下:
./windows &
這時,在開發板上可以看到有三幅圖案被繪製出來,如下圖所示:
進入sql/drilldown目錄,執行如下指令:
./drilldown &
這時,在開發板上可以看到有四個QT畫面被繪製出來,如下圖所示:
進入sql/books目錄,執行如下指令:
./books &
這時,在開發板上可以看到有一個對話框被繪製出來,如下圖所示:
進入sql/masterdetail目錄,執行如下指令:
./masterdetail &
這時,在開發板上可以看到有一個對話框繪製出來,如下圖所示:
默認buildroot編譯出了很多示例,這裡不帶一一列舉,有興趣的讀者可以自行嘗試。
安裝QT Creator
通常我們使用QT Creator創建基於QT的工程。在QT官網下載最新的QT安裝包,下載地址如下:
http://download.qt.io/official_releases/qt/
打開連結頁面如下:
點擊5.1,下載最新的安裝包,得到名為qt-linux-opensource-5.1.1-x86-offline.run的文件,將它拷貝到ubuntu的用戶目錄,使用如下指令安裝:
./ qt-linux-opensource-5.1.1-x86-offline.run
安裝完成後,QT Creator也就安裝完成了。
編譯QT Creator默認示例
點擊ubuntu圖標,輸入qt,將會查找含有qt的文件,同時,安裝好的QT Creator也會被列出來,如下圖所示:
點擊QT圖標,QT Creator將會運行,如下圖所示:
默認QT的配置是針對X86架構的,這時編譯出來的示例只能在PC機上運行。我們打開Image Composition Example示例,它是一個圖片疊加顯示的示例,找到該示例,單擊即可。打開後的界面如下:
點擊左下腳綠色的三腳箭頭,開始編譯工程。在Compile Output欄會顯示編譯的整個過程。編譯完成後,提示如下:
編譯完成後,編譯出來的映像會自動運行,一個疊加的蝴蝶圖像界面顯示出來了,界面如下:
下面我們將該示例編譯到開發板上運行。使用QT Creator打開上面的示例工程,如下圖所示:
選擇Projects一欄,可以看到最頂端的框圖1,顯示Desktop Qt 5.1.1 GCC 64bit,表明它通過64位的GCC編譯,框圖2表明在debug模式下編譯,相對release模式,debug模式下含有大量調試信息,編譯出來的映像會比較大。通常發布映像時,我們選擇release模式。框圖3指定了編譯的路徑。框圖4指定了qmake和交叉編譯工具。框圖5為調試按鍵,第一個用於選擇編譯模式為debug或release,第二個為運行按鈕,第三個為單步調試按鈕,第四個為編譯按鈕。框圖6為一些輸出信息,如Compile Output,會給出整個編譯的信息。
在框圖1中,點擊Tools->Options,如下圖:
在左測對話框中選擇Build & Run,在後邊選擇Qt Versions,默認Manual為空,Auto-detected選擇的QT5.1默認的qmake,它將運行在X86平台的linux系統上,因此我們要手動添加在ARM平台上運行的qmake。
在buildroot編譯文件系統時,我們選中QT5後,將會在buildroot的output/host/usr/bin目錄生成支持ARM平台的qmake,點擊Add,指向該路徑的qmake:
點擊Open,即在Manual中添加了支持ARM平台的qmake。再選擇Compilers一欄,如下圖所示:
默認Manual為空,Auto-detected為支持X86 32位和64位的GCC,這將直接導致編譯出來只能在PC機上運行。點擊Add,選擇GCC,如下圖所示:
在Name中重命名,以區別ARM和PC平台,如我們命名為GCC-ARM-LINUX,它將會直接顯示在前面QT工程界面的框圖1中,到時我們編譯QT工程時,能夠一目了然,編譯出來的到底是PC平台還是ARM平台。在Compiler path中指定交叉編譯工具,在buildroot中默認已經自動下載並安裝了交叉編譯工具,我們指定到如下路徑即可:
buildroot/output/host/opt/ext-toolchain/bin/arm-linux-gnueabihf-g++
設置完成後,點擊OK,完成設置。
再回到QT的工程界面,我們發現框圖1中的配置仍然針對PC機,點擊框圖1中的Manage Kits,如下圖所示:
注意,這時默認Manual仍然為空,點擊Add,會彈出一個有很多選項的對話框,我們按如下方式配置:
這裡的Name,我們可以點擊Qt Versions,選擇Manual中的qmake,下面就會有名稱出來,將它拷貝過來即可,如下圖所示:
在框圖一中,點擊設置編譯環境的下拉箭頭,如下圖所示:
選擇Change Kit->Qt5.1.1(System),更改後的界面如下:
在框圖2中選擇release,更改後的界面如下:
到此,配置完畢,點擊框圖5中的編譯按鈕,在Compile Output中可以看到編譯信息如下:
這時,在框圖2中指定的目錄中已經生成了能夠在ARM平台運行的映像了,如下圖所示:
將該文件拷貝到x3288開發板上運行,可以看到美麗的蝴蝶圖案顯示出來了。
使用QT Creator創建一個hello world工程
待續
使用QT Creator創建一個LED工程
待續
qttest測試程序
=== 使用QT_demo測試蜂鳴器
測試界面如下:
按住Beep鍵時,蜂鳴器鳴叫,鬆開時,蜂鳴器停止鳴叫。
使用QT_demo調節背光
測試界面如下:
滑動圓形滑輪,可對開發板背光進行亮暗調節。
使用QT_demo測試按鍵
測試界面如下:
按下開發板任一獨立按鍵,圖中界面即會顯示相應鍵值,同時,按下時提示[keydown],抬起時提示[keyup]。目前該功能異常,待調。
使用QT_demo測試ADC電壓
測試界面如下:
使用一字螺絲刀旋轉精密電位器上面的旋轉按鈕,可以看到界面上的Battery Vol的值會相應變化,說明這裡對電位器上ADC電壓採樣有效。目前該功能異常,待調。
使用QT_demo測試音頻
將喇叭或耳機接到開發板的對應接口,點擊下圖中的Play Sound按鈕,會播放測試歌曲:
使用QT_demo測試觸控螢幕
進入如下界面:
單擊綠色矩形框,界面會進入全屏模式,這時我們可以任意書寫來測試觸控螢幕了,測試示例圖片如下:
使用QT_demo測試串口
將需要測試的串口的TXD和RXD短路,再點擊開始測試,界面上會提示對應串口會自發自收0123456789。如果不能自發自收,說明對應的串口硬體有問題。
使用QT_demo測試網絡
將網線連接開發板的有線乙太網接口,點擊界面中的Network Test按鈕,如果網絡已經連通,則會添加DNS,如果沒有連通,則會提示相應錯誤,如下圖所示:
連接網線後測試時,會有如下提示:
使用QT_demo測試TF卡
將SD卡插入開發板的SD卡槽,點擊Tfcard Test,界面上會列出SD卡中的內容。
使用QT_demo測試U盤
將U盤接到開發板的任何一個USB HOST接口,點擊Udisk Test,數據框中會列出U盤中的數據,如果找不到,則會提示無法mount U盤,如圖:
使用QT_demo測試休眠喚醒
點擊Deep Sleep,開發板會進入深度睡眠狀態,這時螢幕會全黑,串口終端也將沒有任何信息提示,只有按下POWER鍵,方可喚醒開發板。
使用QT_demo測試重啟
點擊Reboot按鈕,開發板將重啟。
使用QT_demo測試關機
點擊Poweroff按鈕,開發板將會關機。
linux底層開發示例
播放mp3
將存放有mp3文件的TF卡插到開發板的任意卡槽,使用如下命令掛載TF卡:
cd /
mkdir sdcard
mount /dev/mmcblk1p1 /sdcard
cd sdcard
使用如下命令播放:
./mplayer *.avi
./mplayer *.mp3
連接串口後,可以通過PC鍵盤的0或9調節音量。也可以使用madplayer播放音樂。
在後台運行程序
在上一節中給出了播放音樂的示例,但是這時候mplayer已經占據了終端控制台,在音樂播放完之前,我們無法再使用終端控制台了。又比如我們開發一款產品時,就需要在啟動文件系統後運行一個應用程式,如果運行了一個程序,終端控制台就被占用了,那將極大的限制我們的功能。為止,我們可以將程序放在後台運行。使用方法很簡單,我們只需在執行的指令後面添加一個」&」即可。如播放音樂時使用如下命令:
./mplayer *.mp3 &
中止程序的運行
中止程序的運行有多種方式,最直接的方式就是直接按ctrl+c。如前面我們正在播放一段音頻文件,我們可以按ctrl+c退出程序。但是如果程序在後台運行,那麼我們按ctrl+c就不管用了。這時我們可以使用kill命令。
kill+PID
kill+文件名
螢幕抓圖
本文檔中的各個圖片,都是採用gsnap這個工具進行抓圖的。進入QT圖形界面後,我們能在LCD上看到豐富多彩的人機互動界面。通過gsnap可以抓取到圖形界面精彩的瞬間。在控制台終端輸入如下命令:
gsnap test_pic.jpg /dev/fb0
這時在當前目錄將會保存test_pic.jpg圖像文件。詳細的gsnap移植步驟在後面會有詳細描述。
掛載TF卡
進入QT圖形界面後,在命令終端會有控制台出現,這時可以通過控制台查看文件系統的內容。將TF卡插到開發板的任意卡槽,串口終端會有如下提示:
這時在文件系統的/dev目錄將會自動生成一個名叫mmcblk0p1的塊設備文件。它就是對應的TF卡的設備文件,使用如下命令掛載TF卡到/sdcard目錄:
mkdir /sdcard
mount /dev/mmcblk1p1 /sdcard
查看/scard目錄下的內容,即是我們TF卡中的內容,如下圖所示:
掛載U盤
進入QT圖形界面後,在命令終端會有控制台出現,這時可以通過控制台查看文件系統的內容。插入U盤後,串口終端會有如下提示:
這時在文件系統的/dev目錄將會自動生成一個名叫sda1的塊設備文件。它就是對應的U盤設備文件,使用如下命令掛載U盤到/udisk目錄:
mkdir /udisk
mount /dev/sda1 /udisk
查看/udisk目錄下的內容,即是我們U盤中的內容,如下圖所示:
保存系統時鐘
Linux可以使用date指令更改時間日期。例如:
date -s 201104162350 #设置为2011年4月16日23:50分
hwclock -w #把刚设置的时间存入RTC寄存器
hwclock -s #恢复linux系统时钟为RTC寄存器值,一般将该指令放在rcS中开机自动执行。
掉電保存數據到flash
由於本系統採用了ext4文件系統,因此可以很方便的保存數據,確保掉電後數據不丟失。如我們從U盤中拷備一首歌曲到/root目錄:
cp /mnt/muyangqu.mp3 /
重啟開發板,我們發現在root目錄仍然存在剛才拷備的這首歌曲,說明掉電後數據並沒有丟失。
設置開機自動運行程序
藉助啟動腳本可以設置各種程序開機後自動運行,這點很類似於WINDOWS的Autobat自動批處理文件。啟動腳本位於/etc/init.d/rcS中,我們可以將自己想要開機運行的程序或是開機執行的指令放在rcS裡面。比如我們想製作一個簡單的開機音樂,我們就完全可以在rcS中添加如下語句:
./mplayer start.mp3 &
這時,開機後就會播放名叫start.mp3的音樂了。注意start.mp3需要在當前執行指令所在目錄。
查看開發板內存信息
X4418開發板默認配置1GB DDR3 SDRAM,在uboot啟動時,列印信息上會給出RAM大小信息:
在進入文件系統後,可以通過cat命令查詢Linux系統分配到的SDRAM大小。執行如下命令:
cat /proc/meminfo
linux應用開發示例
本手冊給出的所有應用程式全部在九鼎創展x3288開發板上運行,這裡僅給出了一些比較基礎,常用的應用程式,旨在為用戶打開Linux世界奇妙的大門,用戶定能舉一反三,編寫出屬於自己的更加豐富完美的程序。
聲明:以下所有應用程式全部為九鼎創展科技有限公司原創作品,所有內容全經我們嚴格測試,建議用戶按照下面步驟動手編譯一遍,以增強自己的理解,不推薦直接使用我們提供好的文件。另外,敬請商業人士勿侵犯版權。
Hello World
第一步:生成可執行文件
在x3288_kitkat目錄新建app-ex目錄,在app-ex目錄新建hello目錄,然後在hello目錄下新建hello.c和makefile兩個文件:
vim hello.c
這是一個最基礎的應用程式,如果我們聲明了交叉編譯工具,可以直接敲入命令進行編譯(由於開發板環境缺少c庫,編譯時需要加上-static靜態編譯):
arm-linux--gcc -o hello hello.c -static
編譯完成後,在當前目錄會生成hello可執行文件,我們可以使用file命令查詢執行文件是否為ARM體系文件:
第二步:將可執行文件下載到開發板運行
比較常用的方式有以下四種:
- 通過串口和sz/rz工具
- 複製到存儲媒介,如SD卡,U盤等
- 通過NFS掛載文件系統,這時不用將可執行文件拷備到開發板了,推薦調試使用這種方式!
- 通過ftp傳輸
這裡介紹第二種方法,以TF卡為例,其他方法請讀者自行嘗試。
將生成的hello文件拷備到TF卡,再將TF卡插入開發板的TF卡接口,將TF卡mount到/mnt目錄:
cd /
mount /dev/mmcblk1p1 /mnt
進入mnt目錄,可以看到剛才拷貝的hello文件了:
運行hello:
./hello
列印信息如下:
表明,程序已經成功運行。
前面編譯文件我們需要通過手敲命令執行,我們可以通過編寫makefile來代替手敲的動作。
在hello目錄下新建makefile文件:
vim makefile
直接在hello目錄下敲make就可以生成hello文件。運行的效果和前面的完全相同。
數學函數庫調用
建立程序編譯路徑:
mkdir math
cd math
vim math.c
編輯如下內容:
#include <stdio.h> #include <stdlib.h> #include <math.h> int main(void) { double a=9.0; printf("sqrt(%f)=%f\n",a,sqrt(a)); return 0; }
編輯makefile文件,內容如下:
OBJS=math.o LDFLAGS = -lm CC = $(CURDIR)/../../prebuilt/linux-x86/toolchain/arm-2009q3/bin/arm-none-linux-gnueabi-gcc math:${OBJS} ${CC} -o $@ $^ $(LDFLAGS) -static clean: rm -f math *.o
執行make,將生成的可執行文件math下載到開發板上運行,如下圖所示:
多線程編程示例
建立程序編譯路徑:
mkdir thread
cd thread
vim thread.c
編輯如下內容:
#include<stddef.h> #include<stdio.h> #include<unistd.h> #include"pthread.h" void function1(void); void function2(void); int func_flag=0; pthread_mutex_t mutex; main() { pthread_t reader; pthread_mutex_init(&mutex,NULL); pthread_create(&reader,NULL,(void*)&function1,NULL); function2(); } void function2(void) { while(1) { pthread_mutex_lock(&mutex); if(func_flag==0) { printf("excute function2.\n"); func_flag=1; } pthread_mutex_unlock(&mutex); } } void function1(void) { while(1) { pthread_mutex_lock(&mutex); if(func_flag==1) { printf("excute function1.\n"); func_flag=0; } pthread_mutex_unlock(&mutex); } }
編輯makefile文件,內容如下:
OBJS=thread.o LDFLAGS = -lpthread CC = $(CURDIR)/../../prebuilt/linux-x86/toolchain/arm-2009q3/bin/arm-none-linux-gnueabi-gcc thread:${OBJS} ${CC} -o $@ $^ $(LDFLAGS) -static clean: rm -f thread *.o
執行make,將生成的可執行文件thread下載到開發板上運行,如下圖所示:
多進程編程示例
在Linux下通用調用fork函數創建新的進程。調用fork時,系統將產生一個與當前進程相同的進程。它與原有的進程具有相同的數據,連接關係和在程序同一處執行時的連續性。通常將原有的進程叫父進程,新創建的進程叫子進程。
fork調用將分兩次返回,從父子進程返回。進程創建語法如下:
#include <unistd.h> pid_t pid; pid = fork();
如果pid返回0,表示說明從子進程返回,否則從父進程返回,此時返回的是進程的ID號。我們可以通過getpid()函數來獲得進程的ID號。
首先建立程序編譯目錄:
mkdir process cd process vim process.c
編輯如下內容:
#include<stdio.h> #include<unistd.h> #include<sys/types.h> main() { pid_t pid; pid=fork(); if (pid<0) { printf("fork is error!\n"); return 1; } else if (pid == 0) { while (1) { printf("the child process is running now.pid=%d\n",getpid()); sleep(1);//linux延时函数,延时1秒 } } else { while (1) { printf("the perent process is running now.pid=%d\n",getpid()); sleep(1); } } return 0; }
編輯makefile文件,內容如下:
OBJS=process.o CC = $(CURDIR)/../../prebuilt/linux-x86/toolchain/arm-2009q3/bin/arm-none-linux-gnueabi-gcc process:${OBJS} ${CC} -o $@ $^ $(LDFLAGS) clean: rm -f process *.o
執行make編譯,將生成的可執行文件下載到開發板運行,仔細觀察串口監控信息:
makefile編程示例
在上面的很多測試程序實例中,我們都編寫了一些簡單的makefile文件。下面我們介紹makefile的基本的語法。
makefile就好比批處理文件,裡面寫了一系列集合,當運行make編譯時,便會按makefile提供的命令及順序完成編譯。
這裡我們給出三個文件:main.c,func.c,func.h。主程序在main.c中,在main.c中程序會調用func.c中的函數,func.c中的函數又會用到func.h中定義的變量。
main.c文件內容如下:
#include "func.h" extern int fd; int main(int argc,char **argv) { fd = open(DEVICE_NAME,0);//打开设备 if(fd == -1) { printf("open device %s error \n",DEVICE_NAME); return 0; } else { printf("open device %s ok! \n",DEVICE_NAME); } while(1) { glint_led(); } close(fd); return 0; }
該文件會調用glint_led ()函數,這個函數在func.c中。func.c的內容如下:
#include "func.h" void glint_led(void) { ioctl(fd,LED_ON); sleep(1); ioctl(fd,LED_OFF); sleep(1); }
這裡僅僅是一個讀取按鍵的函數,供main函數調用。該函數需要用到了一些變量,另外還需要一些頭文件支持,這些都存放在func.h中,其內容如下:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #define DEVICE_NAME "/dev/vib" #define LED_ON 0x11 #define LED_OFF 0x22 int fd;
很明顯,這是基於前面的LED測試程序,人為的分成的三個文件。我們的目的不在於分離代碼,而在於學習makefile的編寫方法。
當不使用makefile時,我們使用如下指令編譯:
arm-none-linux-gnueabi-gcc -o mkfile main.c func.c
編譯完成後,將會生成可執行文件mkfile。將它下載到開發板上運行,和前面的按鍵測試完全相同。現在我們嘗試編寫第一個屬於自己的makefile:
mkfile:main.o func.o arm-none-linux-gnueabi-gcc -o mkfilemain.o func.o main.o:main.c arm-none-linux-gnueabi-gcc -c main.c -o main.o func.o:func.c func.h arm-none-linux-gnueabi-gcc -c func.c -o func.o clean: rm -f mkfile *.o
執行make後,編譯器會依次編譯main.c和func.c文件,生成main.o和func.o文件,最後將這兩個.o文件打包到可執行文件mkfile中。這時將mkfile文件下載到開發板運行,效果和前面的是一樣的。我們可以執行make clean指令清除生成的.o文件和可執行文件。
makefile具有很強大的推理功能,我們完全可以簡化上面的代碼。優化後的代碼如下:
OBJS=main.o func.o CC=arm-none-linux-gnueabi-gcc mkfile:${OBJS} ${CC} -o $@ $^ main.o: func.o:func.h clean: rm -f mkfile *.o
可見,這次比上面的完整版要簡化多了。前面通過變量OBJS定義了要編譯的源文件,變量CC給出了交叉編譯工具。$@ 表示目標文件的全稱,即mkfile,$^表示所有被依賴的文件,並以空格分開,即main.o func.o。後面的clean為清除指令,執行make clean後會執行 clean後面的指令。需要注意的是,rm指令後面千萬不要使用$@符號來表征我們要刪除的目標文件,因為這時候$@已經不再表示mkfile了,而表示clean。同樣,使用make指令編譯,一樣能夠生成我們需要的目錄文件mkfile。
上面的makefile使用了變量以及預定義變量。第一句即定義了變量OBJS,將它賦值為main.o func.o,第二句定義了變量CC,將它賦值為一個交叉編譯工具定義。引用變量時,通過${*}表示,這裡*表示前面定義的變量。
上面使用了$@和$^兩個預定義變量,GNU make主要有以下七種預定義變量:
|
不包含擴展名的目標文件名稱 |
|
所有的依賴文件,以空格分開,以出現的先後為序,可能包含重複的依賴文件 |
|
第一個依賴文件的名稱 |
|
所有的依賴文件,以空格分開,這些依賴文件的修改日期比目標的創建日期晚 |
|
目標的完整名稱 |
|
所有的依賴文件,以空格分開,不包含重複的依賴文件 |
|
如果目標是歸檔成員,則該變量表示目標的歸檔成員名稱。例如,如果目標名稱為mytarget.so(image.o),則$@ 為mytarget.so,而$% 為image.o。 |
對比以上幾種編譯方式,我們不然發現,其實最簡的還是第一種,因為它就一句話就搞定了。那麼在makefile中,我們是否也可以精簡到只有一句話呢?答案是肯定的。我們繼續利用makefile強大的推理功能進行簡化,得到如下makefile代碼:
OBJS=main.o func.o CC=arm-none-linux-gnueabi-gcc mkfile:${OBJS} ${CC} -o $@ $^ clean: rm -f mkfile *.o
這次,makefile真正編譯的代碼,就只有上面紅色部分一條指令了。和前面比較,不難發現,單獨對main.c和func.c兩個文件編譯的指令已經去掉了。前面我們提到,makefile具有強大的推理功能,我們在生成目標文件mkfile時,makefile會推理出它需要main.c和func.c兩個文件,因此它首先就會去編譯這兩個文件,最後再執行目標文件的生成。因此我們完全可以將它們省去。
這裡只是makefile的一點基礎,讀者可以藉助於其他書籍對makefile作更深一層的了解。
mplayer移植
有兩種移植mplayer,第一種方法就是直接下載mplayer源碼包,手動配置編譯環境,再通過交叉編譯環境編譯。該方法比較傳統,我們有更方便的方法,直接在buildroot中選中mplayer,再make即可,buildroot會自動下載mplayer源碼包,自動配置編譯環境並編譯。
在buildroot的menuconfig配置選項中,進入Target packages-> Audio and video applications選項,選中mplayer,如下圖所示:
保存退出,在buildroot下直接make,生成文件系統後更新到開發板,mplayer就打包進文件系統了。
madplayer移植
madplayer的移植方法和mplayer的移植方法完全雷同,直接在buildroot中選中madplayer的選項,再make即可。
螢幕抓圖工具gsnap移植
說明:以下步驟基於4.3.3的交叉編譯工具,讀者需修改成x3288對應的交叉編譯工具,其他步驟雷同。
螢幕抓圖的方法有多種,有不少愛好者自己動手寫抓圖小程序。這裡我們使用JPEG庫來處理。具體用到了jpegsrc.v6b.tar.gz和gsnap.tar.gz兩個源碼包。
一:安裝libjpeg
解壓jpeg庫源碼包,進入根目錄:
tar zxf jpegsrc.v6b.tar.gz
cd jpeg-6b
二:配置編譯環境:
./configure --prefix=/usr/local/arm/4.3.3/arm-none-linux-gnueabi
--exec-prefix=/usr/local/arm/4.3.3/arm-none-linux-gnueabi --enable-shared --enable-static
三:修改makefile
CC = gcc 修改为 CC = arm-none-linux-gnueabi-gcc
AR = ar ac 修改为 AR = arm-none-linux-gnueabi-ar ac
AR2=ranlib修改为 AR2= arm-none-linux-gnueabi-ranlib
确保—exec-prefix已经设置为/usr/local/arm/4.3.3/arm-none-linux-gnueabi,如果没有,手动设置。
四:在/usr/local/arm/4.3.3/arm-none-linux-gnueabi下建立man/man1目錄:
cd /usr/local/arm/4.3.3/arm-none-linux-gnueabi
mkdir -p man/man1
五:編譯,安裝
make
make install
這時,在/usr/local/arm/4.3.3/arm-none-linux-gnueabi/man/man1目錄下將會生成以下文件:
cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 wrjpgcom.1
在/usr/local/arm/4.3.3/arm-none-linux-gnueabi/lib目錄下生成以下文件:
libjpeg.a libjpeg.la libjpeg.so libjpeg.so.62 libjpeg.so.62.0.0
六:解壓gsnap
tar zxf gsnap.tar.gz
cd gsnap
七:修改makefile
all: arm-none-linux-gnueabi-gcc -g gsnap.c -ljpeg -o gsnap clean: rm -f gsnap
八:編譯,得到可執行文件gsnap
make
九:將jpeg庫文件複製到文件系統的lib目錄,注意保持文件的連結屬性
cp -a libjpeg.s* “文件系统路径”/lib
十:將可執行文件gsnap複製到文件系統的sbin目錄
cp gsnap “文件系统路径”/sbin
十一:重新製作文件系統,下載到開發板上,使用如下命令即可截獲圖形界面:
gsnap 1.jpg /dev/fb0
同樣可以將圖片保持為bmp,png等其他格式。