Mpp是Rockchip為RK3399提供的一套視頻編解碼的api, 并且基于mpp,Rockchip提供了一套gstreamer的編解碼插件。用戶(hù)可以根據(jù)自己的需求,基于gstreamer來(lái)做視頻編解碼的應(yīng)用,或者直接調(diào)用mpp,來(lái)實(shí)現(xiàn)硬件的編解碼加速。
Firefly 發(fā)布的Ubuntu 系統(tǒng), 都已經(jīng)提供了完整的gstremaer 和 mpp支持,并且提供了相應(yīng)的demo,供用戶(hù)開(kāi)發(fā)參考。
-
Ubuntu 16.04 下,gstreamer 1.12 已經(jīng)安裝在/opt/目錄下。
-
Ubuntu 18.04下, gstreamer 1.12 已經(jīng)安裝到系統(tǒng)中。
/usr/local/bin/h264dec.sh 測(cè)試硬件H264解碼。
/usr/local/bin/h264enc.sh 測(cè)試硬件H264編碼。
用戶(hù)可以參照這兩個(gè)腳本,配置自己的gstreamer應(yīng)用。
-
Ubunut 系統(tǒng)下, mpp 相關(guān)dev包都已經(jīng)安裝到系統(tǒng)中。
/opt/mpp/下分別是mpp 編解碼的相關(guān)demo 和 源文件。
RK3399 支持 OpenGL ES1.1/2.0/3.0/3.1。
Firefly 發(fā)布的Ubuntu 系統(tǒng), 都已經(jīng)提供了完整的OpenGL-ES支持。運(yùn)行glmark2-es2
可以測(cè)試openGL-ES支持。 如果要避免屏幕刷新率對(duì)測(cè)試結(jié)果的影響,可以在串口終端上使用以下命令測(cè)試。
# systemctl stop lightdm # export DISPLAY=:0 # Xorg & # glmark2-es2 –off-screen
在Chromium瀏覽器中, 在地址欄輸入:chrome://gpu
可以查看chromium下硬件加速的支持。
Note:
-
EGL 是用arm 平臺(tái)上OpenGL針對(duì)x window system的擴(kuò)展,功能等效于x86下的glx庫(kù)。
-
由于Xorg使用的Driver modesettings 默認(rèn)會(huì)加載libglx.so(禁用glx會(huì)導(dǎo)致某些通過(guò)檢測(cè)glx環(huán)境的應(yīng)用啟動(dòng)失敗), libglx.so會(huì)搜索系統(tǒng)中的dri實(shí)現(xiàn)庫(kù)。但是rk3399 Xorg 2D加速是直接基于DRM實(shí)現(xiàn), 并未實(shí)現(xiàn)dri庫(kù),所以啟動(dòng)過(guò)程中,libglx.so會(huì)報(bào)告如下的錯(cuò)誤 。
這個(gè)對(duì)系統(tǒng)運(yùn)行沒(méi)有任何影響,不需要處理。
-
基于同樣的道理,某些應(yīng)用啟動(dòng)過(guò)程中,也會(huì)報(bào)告如下錯(cuò)誤,不用處理,對(duì)應(yīng)用的運(yùn)行不會(huì)造成影響。
libGL error: unable to load driver: rockchip_dri.so libGL error: driver pointer missing libGL error: failed to load driver: rockchip
-
Firefly之前發(fā)布的某些版本的Ubuntu軟件,默認(rèn)關(guān)閉了加載libglx.so,在某些情況下,運(yùn)行某些應(yīng)用程序會(huì)出現(xiàn)下述錯(cuò)誤:
GdkGLExt-WARNING **: Window system doesn't support OpenGL.
修正的方法如下:
刪除
/etc/X11/xorg.conf.d/20-modesetting.conf
中一下三行配置。Section "Module" Disable "glx" EndSection
Firefly發(fā)布的Ubuntu系統(tǒng),已經(jīng)添加了opencl1.2支持,可以運(yùn)行系統(tǒng)內(nèi)置的clinfo
獲取平臺(tái)opencl相關(guān)參數(shù)。
firefly@firefly:~$ clinfo Platform #0 Name: ARM Platform Version: OpenCL 1.2 v1.r14p0-01rel0-git(966ed26).f44c85cb3d2ceb87e8be88e7592755c3 Device #0 Name: Mali-T860 Type: GPU Version: OpenCL 1.2 v1.r14p0-01rel0-git(966ed26).f44c85cb3d2ceb87e8be88e7592755c3 Global memory size: 1 GB 935 MB 460 kB Local memory size: 32 kB Max work group size: 256 Max work item sizes: (256, 256, 256) …
RK3399 支持神經(jīng)網(wǎng)絡(luò)的GPU加速方案LinuxNN, Firefly發(fā)布的Ubuntu系統(tǒng),已經(jīng)添加了LinuxNN的支持。
在opt/tensorflowbin/下,運(yùn)行test.sh, 即可測(cè)試MobileNet 模型圖像分類(lèi)器的 Demo和MobileNet-SSD 模型的目標(biāo)檢測(cè) Demo
firefly@firefly:/opt/tensorflowbin$ ./test.sh Loaded model mobilenet_ssd.tflite resolved reporter nn version: 1.0.0 findAvailableDevices filename:libarmnn-driver.so d_info:40432 d_reclen:40s [D][ArmnnDriver]: Register Service: armnn (version: 1.0.0)! first invoked time: 1919.17 ms invoked average time: 108.4 ms validCount: 26 car @ (546, 501) (661, 586) car @ (1, 549) (51, 618) person @ (56, 501) (239, 854) person @ (332, 530) (368, 627) person @ (391, 541) (434, 652) person @ (418, 477) (538, 767) person @ (456, 487) (602, 764) car @ (589, 523) (858, 687) person @ (826, 463) (1034, 873) bicycle @ (698, 644) (1128, 925) write out.jpg succ!
Firefly 發(fā)布的 Ubuntu 系統(tǒng),如果需要默認(rèn)對(duì)系統(tǒng)的顯示方向做旋轉(zhuǎn),可以在
/etc/default/xrandr 中修改對(duì)應(yīng)的顯示設(shè)備的方向即可。
firefly@firefly:~$ cat /etc/default/xrandr #!/bin/sh # Rotation can be one of 'normal', 'left', 'right' or 'inverted'. # xrandr --output HDMI-1 --rotate normal # xrandr --output LVDS-1 --rotate normal # xrandr --output EDP-1 --rotate normal # xrandr --output MIPI-1 --rotate normal # xrandr --output VGA-1 --rotate normal # xrandr --output DP-1 --rotate normal
對(duì)于配有觸摸屏的平臺(tái),如果需要對(duì)觸摸屏的方向做旋轉(zhuǎn),可以在/etc/X11/xorg.conf.d/05-gslX680.conf中修改SwapAxes / InvertX / InvertY三個(gè)值。
firefly@firefly:~$ cat /etc/X11/xorg.conf.d/05-gslX680.conf Section "InputClass" Identifier "gslX680" MatchIsTouchscreen "on" MatchProduct "gslX680" Driver "evdev" Option "SwapAxes" "off" # Invert the respective axis. Option "InvertX" "off" Option "InvertY" "off" EndSection
官方的 Ubuntu 系統(tǒng)中自帶屏幕鍵盤(pán),可以在菜單欄中點(diǎn)擊打開(kāi):
開(kāi)發(fā)板一般都有2個(gè)或以上的音頻設(shè)備。常見(jiàn)的是耳機(jī)和 HDMI 這兩個(gè)設(shè)備的音頻輸出。下面是音頻設(shè)置的例子,供用戶(hù)參考。
系統(tǒng)自帶的音頻文件在 /usr/share/sound/alsa/
目錄中,播放前請(qǐng)先查看聲卡設(shè)備:
root@firefly:~# aplay -l **** List of PLAYBACK Hardware Devices **** card 0: rockchiprt5640c [rockchip,rt5640-codec], device 0: ff890000.i2s-rt5640-aif1 rt5640-aif1-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: rkhdmidpsound [rk-hdmi-dp-sound], device 0: HDMI-DP multicodec-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0
然后指定聲卡播放音頻,其中聲卡 card0 的設(shè)備0對(duì)應(yīng)的是耳機(jī)口,card1 的設(shè)備0對(duì)應(yīng)的是 HDMI。一般播放音頻命令是 aplay -Dhw:0,0 Fornt_Center.wav
,但系統(tǒng)自帶的音頻文件是單聲道的,所以為了防止播放失敗,可以按照下面的命令進(jìn)行播放:
#選擇耳機(jī)口輸出音頻文件 root@firefly:/usr/share/sounds/alsa# aplay -Dplughw:0,0 Front_Center.wav Playing WAVE 'Front_Center.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono #選擇 HDMI 輸出音頻文件 root@firefly:/usr/share/sounds/alsa# aplay -Dplughw:1,0 Front_Center.wav Playing WAVE 'Front_Center.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
在圖形界面中,播放準(zhǔn)備好的音頻文件,然后點(diǎn)擊聲音圖標(biāo),打開(kāi) Sound Setting
,選擇到 Configuration
??梢钥吹絻蓚€(gè)聲卡設(shè)備,例如設(shè)置為 HDMI 輸出音頻,則把 HDMI 的聲卡設(shè)備選擇為 Output
,另一個(gè)聲卡設(shè)置為 Off
。(如果 HDMI 無(wú)聲或者聲音小,可以試試按 HDMI 屏上的物理按鍵調(diào)高音量)
在系統(tǒng)中,可以根據(jù)用戶(hù)需求自行設(shè)置應(yīng)用程序開(kāi)機(jī)自動(dòng)啟動(dòng)。
在系統(tǒng)菜單欄中依次選擇:Preferences
-> Default applications for LXSession
,打開(kāi)設(shè)置界面。
在設(shè)置界面的 Launching applocations
一欄中可以設(shè)置應(yīng)用默認(rèn)的打開(kāi)方式:
在 Autostart
一欄中就可以選擇用戶(hù)需要開(kāi)機(jī)啟動(dòng)的應(yīng)用。例如藍(lán)牙默認(rèn)是開(kāi)機(jī)不啟動(dòng)的,如果需要讓它開(kāi)機(jī)自動(dòng)啟動(dòng),就把 Blueman Applet
的勾打上,就可以實(shí)現(xiàn)開(kāi)機(jī)自動(dòng)啟動(dòng)藍(lán)牙:
ADB,全稱(chēng) Android Debug Bridge,是 Android 的命令行調(diào)試工具,可以完成多種功能,如跟蹤系統(tǒng)日志,上傳下載文件,安裝應(yīng)用等。以 Firefly-RK3399 為例,為了在 Ubuntu 系統(tǒng)也能使用 ADB 工具進(jìn)行調(diào)試,我們移植了 ADB 服務(wù)。但由于并非 Android 系統(tǒng),很多 ADB 命令類(lèi)似 adb logcat
、adb install
等不能使用,僅作為普通的調(diào)試輔助工具,可以進(jìn)行 shell 交互、上傳下載文件等操作。同樣的網(wǎng)絡(luò)遠(yuǎn)程 ADB 調(diào)試也不能使用。
在 Ubuntu 系統(tǒng)中,執(zhí)行:
sudo apt-get install android-tools-adb
在內(nèi)核目錄下,打開(kāi)內(nèi)核配置選項(xiàng)菜單:
make firefly_linux_defconfig make menuconfig
進(jìn)入內(nèi)核配置菜單后依次選擇:Device Drivers
-> USB Support
-> USB Gadget Support
。
在 USB Gadget Driver
選項(xiàng)中選擇到 USB functions configurable through configfs
。
同時(shí)再選擇上 Function filesystem (FunctionFS)
。
<*> USB Gadget Drivers (USB functions configurable through configfs) ---> USB functions configurable through configfs [*] Function filesystem (FunctionFS)
接著在 kernel
目錄下編譯內(nèi)核:
make rk3399-firefly.img -j12
編譯完成后將內(nèi)核燒錄到開(kāi)發(fā)板中,燒錄過(guò)程請(qǐng)參考維基教程:升級(jí)固件中的分區(qū)鏡像燒寫(xiě)部分。
安裝了 ADB 后,用 Micro USB OTG 線(xiàn)連接開(kāi)發(fā)板和 PC 機(jī)。然后通過(guò)命令 adb devices
查看是否有設(shè)備連接:
firefly@Desktop:~$ adb devices List of devices attached 0123456789ABCDEF device
從返回的信息可以看到已經(jīng)查找到了設(shè)備,表明設(shè)備已經(jīng)成功連接。
設(shè)備連接成功后,輸入命令 adb shell
即可進(jìn)入命令行模式:
firefly@Desktop:~$ adb shell #
此狀態(tài)下是看不到命令行當(dāng)前的路徑,同時(shí) Tab 鍵補(bǔ)全功能失效,需要進(jìn)入一個(gè)用戶(hù)中才可以正常操作。
firefly@Desktop:~$ adb shell # su firefly To run a command as administrator (user "root"), use "sudo
". See "man sudo_root" for details. firefly@firefly:/$ #到這里命令行就可以正常使用了
用戶(hù)也可以使用命令 adb shell /bin/bash
,也可以進(jìn)入正常的命令行模式。
可以輸入 adb help
查看命令行幫助信息,注意并不是所有命令都可以使用,幫助信息只做參考。
開(kāi)發(fā)板上的串口分兩種,一種是普通串口另外一種是通過(guò)轉(zhuǎn)換芯片把SPI轉(zhuǎn)換而成的串口。轉(zhuǎn)換而成的串口和普通串口功能完全一致但是需要注意它們的設(shè)備文件名是不一樣的。下面是兩者的區(qū)別:
//普通串口 root@firefly:~# ls /dev/ttyS* ttyS0 ttyS1 ttyS2 ttyS3 //SPI轉(zhuǎn)串口 root@firefly:~# ls /dev/ttysWK* ttysWK0 ttysWK1 ttysWK2 ttysWK3
以 ttyS4
為例,查看串口波特率命令:
root@firefly:~# stty -F /dev/ttyS4 speed 9600 baud; line = 0; -brkint -imaxbel
設(shè)置波特率命令:
//設(shè)置波特率為115200 root@firefly:~# stty -F /dev/ttyS4 ospeed 115200 ispeed 115200 cs8 //查看確認(rèn)是否已經(jīng)修改 root@firefly:~# stty -F /dev/ttyS4 speed 115200 baud; line = 0; -brkint -imaxbel root@firefly:~#
在做環(huán)回收發(fā)測(cè)試的時(shí)候回顯功能會(huì)影響到我們的測(cè)試結(jié)果,所以在環(huán)回測(cè)試或者其他特殊情況下需要關(guān)閉回顯。以下是關(guān)閉回顯的命令:
//關(guān)閉回顯示 root@firefly:~# stty -F /dev/ttyS4 -echo -echoe -echok //查看所有功能的配置,檢查是否已經(jīng)關(guān)閉?!?”號(hào)代表該功能已經(jīng)關(guān)閉 root@firefly:~# stty -F /dev/ttyS4 -a | grep echo isig icanon iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc
在實(shí)際應(yīng)用中實(shí)際發(fā)送數(shù)據(jù)和我們希望發(fā)送的數(shù)據(jù)可能存在差別,例如多了回車(chē)或者其他特殊字符。利用 stty
可以把發(fā)送接收設(shè)置成 raw
模式確保發(fā)送接收的是原始數(shù)據(jù),以下是設(shè)置命令:
root@firefly:~# stty -F /dev/ttyS4 raw
串口有 2 種工作模式分別是中斷模式和 DMA 模式。
中斷模式
內(nèi)核默認(rèn)把串口配置成中斷模式所以不需要做任何修改。中斷模式下傳輸速率比較快但是在傳大量數(shù)據(jù)的時(shí)候很容易丟包或者出錯(cuò),所以當(dāng)數(shù)據(jù)量比較大的時(shí)候請(qǐng)不要使用中斷模式。
DMA 模式
DMA 模式主要是傳輸大量數(shù)據(jù)的時(shí)候使用。內(nèi)核會(huì)為串口提供一個(gè)緩存空間接收數(shù)據(jù)來(lái)盡量降低串口傳輸?shù)膩G包率。
注意: 緩存空間限默認(rèn)大小為 8K
如果一次傳輸超過(guò)緩存大小就會(huì)丟包,所以使用 DMA 模式的話(huà)需要發(fā)送端需要分包發(fā)送。
設(shè)備樹(shù)文件配置
&uart4 { status = "okay"; + dmas = <&dmac_peri 8>, <&dmac_peri 9>; + dma-names = "tx", "rx"; };
DMA 模式并不能提高傳輸速率,相反因?yàn)樾枰彺?,傳輸速率?huì)有所下降,所以如果不是需要傳輸大量數(shù)據(jù)的話(huà)不要使用 DMA 模式。
不管是中斷模式還有 DMA 模式都無(wú)法保證數(shù)據(jù)傳輸萬(wàn)無(wú)一失,因?yàn)殚L(zhǎng)時(shí)間傳輸大量數(shù)據(jù)的時(shí)候 DDR、CPU 變頻或者占用率過(guò)高都可能導(dǎo)致上層處理數(shù)據(jù)不及時(shí)導(dǎo)致丟包,這個(gè)時(shí)候就需要是用流控了。流控分兩種,一種是軟件流控另一種為硬件流控,下面只介紹硬件流控的使用。
硬件支持
硬件流控需要有硬件支持,開(kāi)發(fā)板的串口 CTX
和 RTX
腳需要和設(shè)備相連。
注意: 開(kāi)發(fā)板不是所有串口都支持硬件流控,請(qǐng)先從原理圖上確認(rèn)硬件是否支持
設(shè)備樹(shù)文件配置
uart3: serial@ff1b0000 { compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart"; reg = <0x0 0xff1b0000 0x0 0x100>; clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>; clock-names = "baudclk", "apb_pclk"; interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH 0>; reg-shift = <2>; reg-io-width = <4>; pinctrl-names = "default"; + pinctrl-0 = <&uart3_xfer &uart3_cts &uart3_rts>; status = "disabled"; };
應(yīng)用層設(shè)置
上層也需要打開(kāi)流控的設(shè)置,這里介紹 stty 如何打開(kāi)流控如果你使用的是其他應(yīng)用程序請(qǐng)從應(yīng)用中打開(kāi)流控。
//打開(kāi)流控 root@firefly:~# stty -F /dev/ttyS4 crtscts //檢測(cè)流控是否打開(kāi),“-”號(hào)代表該功能已經(jīng)關(guān)閉 root@firefly:~# stty -F /dev/ttyS4 -a | grep crtscts -parenb -parodd -cmspar cs8 hupcl -cstopb cread clocal crtscts
帶有 MIPI CSI
接口的 RK3399 板子都添加了雙 MIPI 攝像頭 OV13850
的支持,應(yīng)用中也添加了攝像頭的例子。下面介紹一下相關(guān)配置。
以 rk3399-firefly-aiojd4.dts
為例,這些都是攝像頭需要打開(kāi)的配置。由于內(nèi)核已經(jīng)添加了雙 MIPI 攝像頭的支持,所以這里配置了兩個(gè)攝像頭,如果只使用一個(gè)攝像只需要打開(kāi)其中一個(gè)攝像頭就可以了。
//電源管理 &vcc_mipi { status = "okay"; }; &dvdd_1v2 { status = "okay"; }; //MIPI 攝像頭1 &ov13850 { status = "okay"; }; &rkisp1_0 { status = "okay"; }; &mipi_dphy_rx0 { status = "okay"; }; &isp0_mmu { status = "okay"; }; //MIPI 攝像頭2 &ov13850_1 { status = "okay"; }; &rkisp1_1 { status = "okay"; }; &mipi_dphy_tx1rx1 { status = "okay"; }; &isp1_mmu { status = "okay"; };
注意: 如果使用的是 core-3399
核心板加上 DIY 底板,可能需要修改相應(yīng)的 GPIO 屬性。
在運(yùn)行腳本之前先確認(rèn)一下 OV13850
設(shè)備是否注冊(cè)成功,下面是成功的內(nèi)核日志:
root@firefly:~# dmesg | grep ov13850 //MIPI 攝像頭1 [ 1.276762] ov13850 1-0036: GPIO lookup for consumer reset [ 1.276771] ov13850 1-0036: using device tree for GPIO lookup [ 1.276803] of_get_named_gpiod_flags: parsed 'reset-gpios' property of node '/i2c@ff110000/ov13850@36[0]' - status (0) [ 1.276855] ov13850 1-0036: Looking up avdd-supply from device tree [ 1.277034] ov13850 1-0036: Looking up dovdd-supply from device tree [ 1.277170] ov13850 1-0036: Looking up dvdd-supply from device tree [ 1.277535] ov13850 1-0036: GPIO lookup for consumer pwdn [ 1.277544] ov13850 1-0036: using device tree for GPIO lookup [ 1.277575] of_get_named_gpiod_flags: parsed 'pwdn-gpios' property of node '/i2c@ff110000/ov13850@36[0]' - status (0) [ 1.281862] ov13850 1-0036: Detected OV00d850 sensor, REVISION 0xb2 //MIPI 攝像頭2 [ 1.284442] ov13850 1-0046: GPIO lookup for consumer pwdn [ 1.284461] ov13850 1-0046: using device tree for GPIO lookup [ 1.284523] of_get_named_gpiod_flags: parsed 'pwdn-gpios' property of node '/i2c@ff110000/ov13850@46[0]' - status (0) [ 1.288235] ov13850 1-0046: Detected OV00d850 sensor, REVISION 0xb2
在 /dev
下應(yīng)該生成相關(guān)設(shè)備文件:
root@firefly:~# ls /dev/video //MIPI 攝像頭1 video0 video1 video2 video3 //MIPI 攝像頭2 video4 video5 video6 video7
注意: 同理,如果只使用一個(gè)攝像頭,只需要注冊(cè)一個(gè)攝像頭設(shè)備就可以了。
在官方提供的 Ubuntu 系統(tǒng)中已經(jīng)添加了攝像頭測(cè)試腳本 /usr/local/bin/dual-camera-rkisp.sh
,其內(nèi)容為:
#!/bin/bash export DISPLAY=:0 export XAUTHORITY=/home/firefly/.Xauthority export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin export LD_LIBRARY_PATH=/usr/lib/gstreamer-1.0 WIDTH=640 HEIGHT=480 SINK=gtksink /etc/init.d/S50set_pipeline start # camera closed to the border of the board gst-launch-1.0 rkisp device=/dev/video0 io-mode=1 analyzer=1 enable-3a=1 path-iqf=/etc/cam_iq.xml ! video/x-raw,format=NV12,width=${WIDTH},hei ght=${HEIGHT}, framerate=30/1 ! videoconvert ! $SINK & # the other camera gst-launch-1.0 rkisp device=/dev/video4 io-mode=1 analyzer=1 enable-3a=1 path-iqf=/etc/cam_iq.xml ! video/x-raw,format=NV12,width=${WIDTH},hei ght=${HEIGHT}, framerate=30/1 ! videoconvert ! $SINK & wait
運(yùn)行腳本即可,結(jié)果如圖所示:
USB 以太網(wǎng),主要實(shí)現(xiàn)的是將開(kāi)發(fā)板的 OTG 接口做外設(shè)模式,模擬成一個(gè)網(wǎng)絡(luò)接口,然后主機(jī)通過(guò) USB 連接開(kāi)發(fā)板并通過(guò)開(kāi)發(fā)板訪問(wèn)互聯(lián)網(wǎng)。以下是基于 Firefly-RK3399 開(kāi)發(fā)板進(jìn)行的具體操作。
操作環(huán)境:
-
Ubuntu 系統(tǒng)的 PC 機(jī)
-
Firefly-RK3399 開(kāi)發(fā)板
在內(nèi)核目錄下,打開(kāi)內(nèi)核配置選項(xiàng)菜單:
make firefly_linux_defconfig make menuconfig
進(jìn)入內(nèi)核配置菜單后依次選擇:Device Drivers
-> USB Support
-> USB Gadget Support
。
將 USB Gadget Driver
設(shè)置成編譯成模塊,然后可以在下邊找到 Ethernet Gadget (with CDC Ethernet support)
選項(xiàng),同樣選擇編譯成模塊。同時(shí)要選擇上 RNDIS support
。
<M> USB Gadget Drivers <M> USB functions configurable through configfs <M> Ethernet Gadget (with CDC Ethernet support) [*] RNDIS support (NEW)
接著在 kernel
目錄下編譯內(nèi)核:
make rk3399-firefly.img -j12
編譯完成后將內(nèi)核燒錄到開(kāi)發(fā)板中,燒錄過(guò)程請(qǐng)參考維基教程:升級(jí)固件中的分區(qū)鏡像燒寫(xiě)部分。然后將內(nèi)核目錄下生成的下列模塊復(fù)制到開(kāi)發(fā)板中:
-
drivers/usb/gadget/function/u_ether.ko
-
drivers/usb/gadget/function/usb_f_ecm_subset.ko
-
drivers/usb/gadget/function/usb_f_ecm.ko
-
drivers/usb/gadget/function/usb_f_rndis.ko
-
drivers/usb/gadget/function/usb_f_eem.ko
-
drivers/usb/gadget/legacy/g_ether.ko
-
drivers/usb/gadget/libcomposite.ko
然后在開(kāi)發(fā)板上,依次加載上述模塊:
insmod libcomposite.ko insmod u_ether.ko insmod usb_f_ecm_subset.ko insmod usb_f_rndis.ko insmod usb_f_ecm.ko insmod usb_f_eem.ko insmod g_ether.ko
注意: 要先加載 libcomposite.ko
和 u_ether.ko
,后面的模塊才可以加載進(jìn)去。
用數(shù)據(jù)線(xiàn)連接 PC 機(jī)和開(kāi)發(fā)板的 OTG 接口,在 PC 機(jī)中執(zhí)行 lsusb
命令可以查看到 USB 以太網(wǎng)設(shè)備,即說(shuō)明連接成功。
firefly@Desktop:~$ lsusb Bus 002 Device 003: ID 09da:5814 A4Tech Co., Ltd. Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 005: ID 04f2:b2ea Chicony Electronics Co., Ltd Integrated Camera [ThinkPad] Bus 001 Device 004: ID 0a5c:21e6 Broadcom Corp. BCM20702 Bluetooth 4.0 [ThinkPad] Bus 001 Device 003: ID 147e:1002 Upek Biometric Touchchip/Touchstrip Fingerprint Sensor Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 003 Device 003: ID 0525:a4a2 Netchip Technology, Inc. Linux-USB Ethernet/RNDIS Gadget Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
輸出信息中 ID 0525:a4a2 Netchip Technology, Inc. Linux-USB Ethernet/RNDIS Gadget 即為 USB 網(wǎng)卡設(shè)備。
開(kāi)發(fā)板插入網(wǎng)線(xiàn),使開(kāi)發(fā)板可以連接外網(wǎng)。
-
在開(kāi)發(fā)板中 IP 的設(shè)置:
輸入執(zhí)行 ifconfig -a
命令,可以查看到以下信息:
root@firefly:~# ifconfig -a # eth0 是有線(xiàn)網(wǎng)卡 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 168.168.100.48 netmask 255.255.0.0 broadcast 168.168.255.255 inet6 fe80::1351:ae2f:442e:e436 prefixlen 64 scopeid 0x20<link> ether 8a:4f:c3:77:94:ac txqueuelen 1000 (Ethernet) RX packets 9759 bytes 897943 (897.9 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 236 bytes 35172 (35.1 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 42 base 0x8000 ... # usb0 是虛擬的 usb 網(wǎng)卡 usb0: flags=4098<BROADCAST,MULTICAST> mtu 1500 ether 4a:81:b1:34:d2:ad txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
然后給 usb0 網(wǎng)卡自定義一個(gè)適當(dāng)?shù)?IP:
注意要設(shè)置 usb0 的 IP 和有線(xiàn)網(wǎng)卡 eth0 的 IP 不在同一網(wǎng)段!!
ifconfig usb0 192.168.1.101
-
在 PC 機(jī)中 IP 的設(shè)置:
# 先查看 USB 虛擬網(wǎng)卡 firefly@Desktop:~$ ifconfig enp0s20u2i1: flags=4163 mtu 1500 inet 192.168.2.90 netmask 255.255.255.0 broadcast 192.168.2.255 inet6 fe80::871c:b87e:1327:7fd4 prefixlen 64 scopeid 0x20
ether 46:fe:6e:97:ee:a6 txqueuelen 1000 (以太網(wǎng)) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 1 bytes 54 (54.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ... # 設(shè)置 USB 網(wǎng)卡的 IP 地址和開(kāi)發(fā)板的 usb0 的 IP 地址在同一網(wǎng)段 firefly@Desktop:~$ sudo ifconfig enp0s20u2i1 192.168.1.100 #設(shè)置默認(rèn)網(wǎng)關(guān):要設(shè)置為開(kāi)發(fā)板 usb0 的 ip 地址,因?yàn)楹竺嬉ㄟ^(guò) usb0 來(lái)進(jìn)行流量的轉(zhuǎn)發(fā) firefly@Desktop:~$ sudo route add default gw 192.168.1.101
設(shè)置完開(kāi)發(fā)板和 PC 機(jī)的 IP 后,互相是可以 ping 通的,PC 機(jī)也可以用 ssh
命令登錄到開(kāi)發(fā)板。
在開(kāi)發(fā)板上:首先打開(kāi) IPv4 的轉(zhuǎn)發(fā)功能:
echo 1 > /proc/sys/net/ipv4/ip_forward
如果希望每次重啟開(kāi)發(fā)板后都自動(dòng)打開(kāi)轉(zhuǎn)發(fā)功能,請(qǐng)直接修改 /etc/sysctl.conf
文件的 net.ipv4.ip_forward
值為1。修改文件參數(shù)后要執(zhí)行 sysctl -p
命令重新載入 /etc/sysctl.conf
文件,使 IPv4 轉(zhuǎn)發(fā)功能生效。
添加規(guī)則進(jìn)行流量轉(zhuǎn)發(fā):
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 168.168.100.48
現(xiàn)在 PC 主機(jī)就可以訪問(wèn)網(wǎng)絡(luò)了。如果 PC 機(jī)可以 ping 通開(kāi)發(fā)板的 usb0 和 eth0,但是無(wú)法上外網(wǎng),則需要修改 PC 機(jī)的 DNS,在 /etc/resolv.conf
中做以下添加:
nameserver 8.8.8.8 nameserver 8.8.4.4
配置過(guò)程中要注意以下幾點(diǎn):
-
對(duì)應(yīng)好上述步驟中自己設(shè)備上的各個(gè) IP 地址,注意開(kāi)發(fā)板上的 USB 虛擬網(wǎng)卡 IP 和有線(xiàn)網(wǎng)絡(luò) IP 不在同一網(wǎng)段;
-
PC 機(jī)虛擬 USB 網(wǎng)卡的網(wǎng)關(guān)要設(shè)置為開(kāi)發(fā)板虛擬 USB 網(wǎng)卡的 IP 地址;
-
開(kāi)發(fā)板上的虛擬網(wǎng)卡 IP 地址、IP 轉(zhuǎn)發(fā)功能、流量轉(zhuǎn)發(fā)規(guī)則等設(shè)置會(huì)在設(shè)備重啟后恢復(fù),用戶(hù)可以自行查找資料如何開(kāi)機(jī)自動(dòng)設(shè)置這些配置。
根文件系統(tǒng)除了可以使用在內(nèi)部的 eMMC 中的,還可以使用外部存儲(chǔ)設(shè)備的根文件系統(tǒng),如 SD 卡,U 盤(pán)等。以下是以 SD 卡為例,在 Firefly-RK3399 開(kāi)發(fā)板上實(shí)現(xiàn)掛載外部存儲(chǔ)設(shè)備的根文件系統(tǒng)。
在 PC 機(jī)上插入 SD 卡,用 gdisk
工具分出一個(gè)裝載根文件系統(tǒng)的分區(qū):
#用戶(hù)請(qǐng)用 `fdisk -l` 查詢(xún) SD 卡設(shè)備名是什么,在用 gdisk 命令進(jìn)入對(duì)應(yīng)的設(shè)備 sudo gdisk /dev/sdb GPT fdisk (gdisk) version 1.0.3 Partition table scan: MBR: protective BSD: not present APM: not present GPT: present Found valid GPT with protective MBR; using GPT. Command (? for help): ------------------------------------------------------------------- #輸入 ? 查看幫助信息 # 按 p 顯示 SD 卡當(dāng)前已有分區(qū),由于使用的 SD 卡暫未創(chuàng)建分區(qū),所以沒(méi)有查詢(xún)到分區(qū)信息 Command (? for help): p Disk /dev/sdb: 15278080 sectors, 7.3 GiB Model: CARD-READER Sector size (logical/physical): 512/512 bytes Disk identifier (GUID): 5801AE61-92ED-42FB-A144-E522E8E15827 Partition table holds up to 128 entries Main partition table begins at sector 2 and ends at sector 33 First usable sector is 34, last usable sector is 15278046 Partitions will be aligned on 2048-sector boundaries Total free space is 15278013 sectors (7.3 GiB) Number Start (sector) End (sector) Size Code Name ------------------------------------------------------------------- #創(chuàng)建新的分區(qū),請(qǐng)用戶(hù)根據(jù)自身實(shí)際情況創(chuàng)建合適的分區(qū)大小給根文件系統(tǒng) Command (? for help): n #輸入 n 創(chuàng)建新分區(qū) Partition number (1-128, default 1): 1 #輸入1創(chuàng)建第一個(gè)分區(qū) First sector (34-15278046, default = 2048) or {+-}size{KMGTP}: #直接按回車(chē),使用默認(rèn)值 Last sector (2048-15278046, default = 15278046) or {+-}size{KMGTP}: +3G #創(chuàng)建分區(qū)大小為3G Current type is 'Linux filesystem' Hex code or GUID (L to show codes, Enter = 8300): #按回車(chē)使用默認(rèn)值 Changed type of partition to 'Linux filesystem' ------------------------------------------------------------------- #創(chuàng)建完成后,輸入 i,可以查看分區(qū)的 unique GUID Command (? for help): i Using 1 Partition GUID code: 0FC63DAF-8483-4772-8E79-3D69D8477DE4 (Linux filesystem) Partition unique GUID: 6278AF5D-BC6B-4213-BBF6-47D333B5CB53 #使用的是該分區(qū)的 unique GUID,記下前12位即可 First sector: 2048 (at 1024.0 KiB) Last sector: 6293503 (at 3.0 GiB) Partition size: 6291456 sectors (3.0 GiB) Attribute flags: 0000000000000000 Partition name: 'Linux filesystem' ------------------------------------------------------------------- #輸入 wq 保存修改并退出 Command (? for help): wq Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING PARTITIONS!! Do you want to proceed? (Y/N): y OK; writing new GUID partition table (GPT) to /dev/sdb. Warning: The kernel is still using the old partition table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8) The operation has completed successfully.
把新創(chuàng)建的分區(qū)進(jìn)行格式化。
# 注意 sdb1 表示 SD 卡對(duì)應(yīng)分區(qū)設(shè)備名,請(qǐng)用戶(hù)根據(jù)實(shí)際情況填入 sudo mkfs.ext4 /dev/sdb1
格式化完成后,使用 dd
命令,將制作好的根文件系統(tǒng)燒寫(xiě)到 SD 卡剛新建的分區(qū)中。(根文件系統(tǒng)的制作可以參考Ubuntu 根文件系統(tǒng)的制作)
# 用戶(hù)請(qǐng)根據(jù)實(shí)際情況填寫(xiě)根文件系統(tǒng)鏡像的路徑和 SD 卡對(duì)應(yīng)分區(qū)設(shè)備名 dd if=/rootfs_path/rootfs.img of=/dev/sdb1
首先要修改設(shè)備樹(shù)文件,打開(kāi)對(duì)應(yīng)的 dts 文件,在根節(jié)點(diǎn)下重寫(xiě) chosen
節(jié)點(diǎn)下的 bootargs
參數(shù)的 root
值為寫(xiě)入了根文件系統(tǒng)的 SD 卡分區(qū)的 unique GUID:
#將 root 的值改為獲取到的 unique GUID 值的前12位 chosen { bootargs = "earlycon=uart8250,mmio32,0xff1a0000 swiotlb=1 console=ttyFIQ0 rw root=PARTUUID=6278AF5D-BC6B rootfstype=ext4 rootwait"; };
修改完成后編譯并燒錄至開(kāi)發(fā)板中。
SD 卡的根文件系統(tǒng)燒錄完成后,插入開(kāi)發(fā)板的 TF 卡槽中,開(kāi)機(jī)即可進(jìn)入到 SD 的根文件系統(tǒng)中。
注意事項(xiàng):
-
在操作前請(qǐng)注意備份 U 盤(pán)或者 SD 卡內(nèi)的重要文件,避免丟失;
-
操作時(shí)請(qǐng)確認(rèn)自己的 SD 卡對(duì)應(yīng)的設(shè)備名;
-
dts 文件中
root
參數(shù)的值使用的是 unique GUID,記下前12位即可。用戶(hù)也可以根據(jù)gdisk
的幫助信息自行修改這個(gè)值。
網(wǎng)絡(luò)啟動(dòng),是用 TFTP 在服務(wù)器下載內(nèi)核、dtb 文件到目標(biāo)機(jī)的內(nèi)存中,同時(shí)可以用 NFS 掛載網(wǎng)絡(luò)根文件系統(tǒng)到目標(biāo)機(jī)上,實(shí)現(xiàn)目標(biāo)機(jī)的無(wú)盤(pán)啟動(dòng)。以下基于 Firefly-RK3399 作出一個(gè)示例,提供用戶(hù)參考。
準(zhǔn)備工作:
-
Firefly-RK3399 開(kāi)發(fā)板;
-
路由器、網(wǎng)線(xiàn);
-
安裝有 NFS 和 TFTP 的服務(wù)器;
-
一份制作好的根文件系統(tǒng)。
注:示例中使用的是 Ubuntu 系統(tǒng)的 PC 機(jī)作為服務(wù)器,通過(guò)路由器和網(wǎng)線(xiàn)實(shí)現(xiàn)與開(kāi)發(fā)板的連接。用戶(hù)可以根據(jù)自己的實(shí)際情況作調(diào)整,但如果是 PC 機(jī)直連開(kāi)發(fā)板,請(qǐng)使用交叉網(wǎng)線(xiàn)。請(qǐng)確保服務(wù)器和目標(biāo)機(jī)在同一局域網(wǎng)內(nèi)。
1、在服務(wù)器上部署 TFTP 服務(wù):
安裝 TFTP 服務(wù):
sudo apt-get install tftpd-hpa
創(chuàng)建 /tftpboot
目錄并賦予權(quán)限:
mkdir /tftpboot sudo chmod 777 /tftpboot
然后修改 TFTP 服務(wù)器的配置文件 /etc/default/tftpd-hpa
,修改內(nèi)容為:
# /etc/default/tftpd-hpa TFTP_USERNAME="tftp" TFTP_DIRECTORY="/tftpboot" #這個(gè)根據(jù)用戶(hù)實(shí)際的 tftp 目錄設(shè)置 TFTP_ADDRESS="0.0.0.0:69" TDTP_OPTIONS="-c -s -l"
退出修改后重啟 TFTP 服務(wù)器:
sudo service tftpd-hpa restart
在 /tftpboot
目錄中創(chuàng)建一個(gè)文件,測(cè)試 TFTP 服務(wù)是否可用:
firefly@Desktop:~$ cd /tftpboot/ firefly@Desktop:/tftpboot$ touch test firefly@Desktop:/tftpboot$ cd /tmp firefly@Desktop:/tmp$ tftp 127.0.0.1 tftp> get test tftp> q
查看 /tmp
目錄中的文件,如果看到了 test
文件表示 TFTP 服務(wù)器是可用的。
2、在服務(wù)器上部署 NFS 服務(wù):
安裝 NFS 服務(wù)器:
sudo apt-get install nfs-kernel-server
創(chuàng)建共享目錄:
sudo mkdir /nfs sudo chmod 777 /nfs cd /nfs sudo mkdir rootfs sudo chmod 777 rootfs
然后將制作好的根文件系統(tǒng)復(fù)制到 /nfs/rootfs
目錄中。(根文件系統(tǒng)的制作可以參考:Ubuntu 根文件系統(tǒng)的制作)
接著配置 NFS,在 /etc/exports
中添加共享目錄位置:
/nfs/rootfs *(rw,sync,no_root_squash,no_subtree_check)
共享的目錄根據(jù)用戶(hù)實(shí)際情況設(shè)置,其中的”*”代表的是所有用戶(hù)可訪問(wèn)。
重啟 NFS 服務(wù)器:
sudo /etc/init.d/nfs-kernel-server restart
本地掛載共享目錄,測(cè)試 NFS 服務(wù)器是否可用:
sudo mount -t nfs 127.0.0.1:/nfs/rootfs/ /mnt
在 /mnt
目錄下查看到了與 /nfs/rootfs
一致的內(nèi)容,則說(shuō)明 NFS 服務(wù)器部署成功。然后可以解除掛載:
sudo umount /mnt
如果要做到掛載網(wǎng)絡(luò)根文件系統(tǒng),需要在內(nèi)核中做相關(guān)配置,并在 dts 中修改相關(guān)掛載根文件系統(tǒng)的配置。
首先進(jìn)行內(nèi)核配置,在內(nèi)核目錄中執(zhí)行 make menuconfig
,選擇相關(guān)配置:
[*] Networking support ---> Networking options ---> [*] IP: kernel level autoconfiguration [*] IP: DHCP support [*] IP: BOOTP support [*] IP: RARP support File systems ---> [*] Network File Systems ---> [*] Root file system on NFS
修改 rk3399-firefly.dts
配置,在 dts 文件中修改 chosen
節(jié)點(diǎn)下的 bootargs
參數(shù),選擇使用 NFS 掛載遠(yuǎn)程根文件系統(tǒng),內(nèi)容如下。
chosen { bootargs = "earlycon=uart8250,mmio32,0xff1a0000 swiotlb=1 console=ttyFIQ0 root=/dev/nfs rootfstype=ext4 rootwait"; }; #主要是修改 root 的值,root=/dev/nfs 表示通過(guò) NFS 掛載網(wǎng)絡(luò)根文件系統(tǒng)
編譯內(nèi)核:
make ARCH=arm64 rk3399-firefly.img -j12
編譯完成后,將編譯好的內(nèi)核文件 boot.img
和 rk3399-firefly.dtb
文件復(fù)制到 /tftpboot
目錄中:
cp boot.img /tftpboot cp arch/arm64/boot/dts/rockchip/rk3399-firefly.dtb /tftpboot
詳細(xì)說(shuō)明可以參考內(nèi)核目錄中的 kernel/Documentation/filesystems/nfs/nfsroot.txt
請(qǐng)先確保目標(biāo)機(jī)網(wǎng)線(xiàn)已插入,接入到服務(wù)器的局域網(wǎng)內(nèi)。
目標(biāo)機(jī)啟動(dòng)進(jìn)入 U-Boot 命令行模式,設(shè)置以下參數(shù):
=> setenv ipaddr 192.168.31.101 #設(shè)置目標(biāo)機(jī) IP 地址 => setenv serverip 192.168.31.106 #設(shè)置 serverip 為服務(wù)器 IP 地址 #設(shè)置從 TFTP 下載內(nèi)核和 dtb 文件到相應(yīng)地址,用戶(hù)請(qǐng)根據(jù)自己實(shí)際的目標(biāo)機(jī)修改相應(yīng)地址 => setenv bootcmd tftpboot 0x0027f800 boot.img \; tftpboot 0x08300000 rk3399-firefly.dtb \; bootm 0x0027f800 - 0x08300000 #設(shè)置掛載網(wǎng)絡(luò)根文件系統(tǒng),IP 參數(shù)依次為:目標(biāo)機(jī) IP:服務(wù)器 IP:網(wǎng)關(guān):網(wǎng)絡(luò)掩碼:設(shè)備名:off,可以更簡(jiǎn)單的設(shè)置 ip=dhcp,通過(guò) DHXP 自動(dòng)分配 IP => setenv bootargs root=/dev/nfs rw nfsroot=192.168.31.106:/nfs/rootfs,v3 ip=192.168.31.101:192.168.31.106:192.168.31.1:255.255.255.0::eth0:off #如果不想每次開(kāi)機(jī)都設(shè)置一遍,可以保存上面配置的變量 => saveenv Saving Environment to MMC... Writing to MMC(0)... done #啟動(dòng)目標(biāo)機(jī) => boot ethernet@fe300000 Waiting for PHY auto negotiation to complete. done Speed: 100, full duplex Using ethernet@fe300000 device TFTP from server 192.168.31.106; our IP address is 192.168.31.101 Filename 'boot.img'. Load address: 0x27f800 Loading: ################################################################# ################################################################# ################################################################# ################################################################# ################################################################# ################################################## 475.6 KiB/s done Bytes transferred = 20072448 (1324800 hex) Speed: 100, full duplex Using ethernet@fe300000 device TFTP from server 192.168.31.106; our IP address is 192.168.31.101 Filename 'rk3399-firefly.dtb'. Load address: 0x8300000 Loading: ####### 645.5 KiB/s done Bytes transferred = 97212 (17bbc hex) ## Booting Android Image at 0x0027f800 ... Kernel load addr 0x00280000 size 19377 KiB ## Flattened Device Tree blob at 08300000 Booting using the fdt blob at 0x8300000 XIP Kernel Image ... OK Loading Device Tree to 0000000073edc000, end 0000000073ef6bbb ... OK Adding bank: 0x00200000 - 0x08400000 (size: 0x08200000) Adding bank: 0x0a200000 - 0x80000000 (size: 0x75e00000) Total: 912260.463 ms Starting kernel ... ...
在開(kāi)機(jī)內(nèi)核日志中可見(jiàn):
[ 12.146297] VFS: Mounted root (nfs filesystem) on device 0:16.
說(shuō)明已經(jīng)掛載上了網(wǎng)絡(luò)根文件系統(tǒng)。
注意事項(xiàng)
-
確保 TFTP 服務(wù)器、NFS 服務(wù)器可用;
-
確保目標(biāo)機(jī)先插入網(wǎng)線(xiàn)后在開(kāi)機(jī),且和服務(wù)器在同一局域網(wǎng)內(nèi),如果是直連目標(biāo)機(jī)和服務(wù)器,請(qǐng)使用交叉網(wǎng)線(xiàn);
-
內(nèi)核配置中,
Root file system on NFS
依賴(lài)于IP: kernel level autoconfiguration
選項(xiàng),請(qǐng)先選擇IP: kernel level autoconfiguration
,之后才可以找到Root file system on NFS
選項(xiàng); -
在 U-Boot 命令行中,請(qǐng)確認(rèn)
boot.img
燒錄地址和 dtb 文件燒錄地址。(提示:boot.img
的文件結(jié)構(gòu)中,開(kāi)頭有2k的頭文件,然后才是 kernel。所以在 TFTP 下載內(nèi)核到目標(biāo)機(jī)時(shí),要下載到對(duì)應(yīng) kernel 地址減去0x0800的地址上); -
在設(shè)置掛載遠(yuǎn)程根文件系統(tǒng)時(shí),
nfsroot=192.168.31.106:/nfs/rootfs,v3
中的v3
代表 NFS 版本信息,請(qǐng)?zhí)砑由弦员苊獬霈F(xiàn)掛載不成功的問(wèn)題。
本小節(jié)介紹了在線(xiàn)更新的一個(gè)簡(jiǎn)單的流程。將內(nèi)核、U-Boot 或者其他需要更新的文件打包成 deb 安裝包,然后導(dǎo)入到本地包倉(cāng)庫(kù),實(shí)現(xiàn)在開(kāi)發(fā)板上下載并自動(dòng)更新。僅供用戶(hù)參考。
操作中需要升級(jí)內(nèi)核和 U-Boot,事先已經(jīng)準(zhǔn)備好了修改好的相關(guān)文件:uboot.img
、trust.img
、boot.img
。
deb 是 Debian Linux 的軟件包格式,打包最關(guān)鍵的是在 DEBIAN
目錄下創(chuàng)建一個(gè) control
文件。首先創(chuàng)建 deb 工作目錄,然后在 deb 目錄中創(chuàng)建相應(yīng)的目錄和文件:
mkdir deb cd deb mkdir firefly-firmware #創(chuàng)建 firefly-firmware 目錄 cd firefly-firmware mkdir DEBIAN #創(chuàng)建 DEBIAN 目錄,這個(gè)目錄是必須要有的。 mkdir -p usr/share/{kernel,uboot} mv ~/boot.img ~/deb/firefly-firmware/usr/share/kernel #將相應(yīng)文件放到相應(yīng)的目錄 mv ~/uboot.img ~/deb/firefly-firmware/usr/share/uboot mv ~/trust.img ~/deb/firefly-firmware/usr/share/uboot
DEBIAN
目錄下存放的文件是 deb 包安裝的控制文件以及相應(yīng)的腳本文件。
在 DEBIAN
目錄下創(chuàng)建控制文件 control
和腳本文件 postinst
。
control
文件內(nèi)容如下,用于記錄軟件標(biāo)識(shí),版本號(hào),平臺(tái),依賴(lài)信息等數(shù)據(jù)。
Package: firefly-firmware #文件目錄名 Version: 1.0 #版本號(hào) Architecture: arm64 #架構(gòu) Maintainer: neg #維護(hù)人員,自定義即可 Installed-Size: 1 Section: test Priority: optional Descriptionon: This is a deb test
postinst
文件內(nèi)容如下,就是將需要更新的內(nèi)核和 U-Boot 文件用 dd
命令寫(xiě)進(jìn)對(duì)應(yīng)分區(qū)的腳本:
echo "-----------uboot updating------------" dd if=/usr/share/uboot/uboot.img of=/dev/disk/by-partlabel/uboot echo "-----------trust updating------------" dd if=/usr/share/uboot/trust.img of=/dev/disk/by-partlabel/trust echo "-----------kernel updating------------" dd if=/usr/share/kernel/boot.img of=/dev/disk/by-partlabel/boot
說(shuō)明:postinst
腳本,是在解包數(shù)據(jù)后運(yùn)行的腳本,對(duì)應(yīng)的還有:
-
preinst:在解包數(shù)據(jù)前運(yùn)行的腳本;
-
prerm:卸載時(shí),在刪除文件之前運(yùn)行的腳本;
-
postrm:在刪除文件之后運(yùn)行的腳本;
其他相關(guān)知識(shí)點(diǎn)用戶(hù)可以自行了解。這里只用到了 preinst
腳本。
以下是創(chuàng)建好的目錄樹(shù):
deb └── firefly-firmware ├── DEBIAN │ ├── control │ └── postinst └── usr └── share ├── kernel │ └── boot.img └── uboot ├── trust.img └── uboot.img
進(jìn)入 deb 目錄,用 dpkg
命令生成 deb 包:
dpkg -b firefly-firmware firefly-firmware_1.0_arm64.deb
生成 deb 包時(shí),一般按照這種規(guī)范進(jìn)行命名:package_version-reversion_arch.deb
。
首先安裝需要的包:
sudo apt-get install reprepro gnupg
然后用 GnuPG 工具生成一個(gè) GPG 密匙,執(zhí)行命令后請(qǐng)根據(jù)提示操作:
gpg --gen-key
執(zhí)行 sudo gpg --list-keys
可以查看剛剛生成的密匙信息:
sudo gpg --list-keys gpg: WARNING: unsafe ownership on homedir '/home/firefly/.gnupg' gpg: 正在檢查信任度數(shù)據(jù)庫(kù) gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: 深度:0 有效性: 4 已簽名: 0 信任度:0-,0q,0n,0m,0f,4u gpg: 下次信任度數(shù)據(jù)庫(kù)檢查將于 2021-05-29 進(jìn)行 /home/firefly/.gnupg/pubring.kbx -------------------------------- pub rsa3072 2019-05-31 [SC] [有效至:2021-05-30] BCB65788541D632C057E696B8CBC526C05417B76 uid [ 絕對(duì) ] firefly sub rsa3072 2019-05-31 [E] [有效至:2021-05-30]
接下來(lái)創(chuàng)建包倉(cāng)庫(kù),首先創(chuàng)建目錄:
cd /var/www mkdir apt #包倉(cāng)庫(kù)目錄 mkdir -p ./apt/incoming mkdir -p ./apt/conf mkdir -p ./apt/key
把前面生成的密匙導(dǎo)出到倉(cāng)庫(kù)文件夾,請(qǐng)用戶(hù)對(duì)應(yīng)好自己創(chuàng)建的用戶(hù)名和郵箱地址。
gpg --armor --export firefly firefly@t-chip.com > /var/www/apt/key/deb.gpg.key
在 conf
目錄下創(chuàng)建 distributions
文件,其內(nèi)容如下:
Origin: Neg #你的名字 Label: Mian #庫(kù)的名字 Suite: stable #(stable 或 unstable) Codename: bionic #發(fā)布代碼名,可自定義 Version: 1.0 #發(fā)布版本 Architectures: arm64 #架構(gòu) Components: main #組件名,如main,universe等 Description: Deb source test #相關(guān)描述 SignWith: BCB65788541D632C057E696B8CBC526C05417B76 #上面步驟中生成的 GPG 密匙
建立倉(cāng)庫(kù)樹(shù):
reprepro --ask-passphrase -Vb /var/www/apt export
將第2步做好的 deb 包加入到倉(cāng)庫(kù)中:
reprepro --ask-passphrase -Vb /var/www/apt includedeb bionic ~/deb/firefly-firmware_1.0_arm64.deb
可以查看庫(kù)中添加的文件:
root@Desktop:~# reprepro -b /var/www/apt/ list bionic bionic|main|arm64: firefly-firmware 1.0
你的包已經(jīng)加入了倉(cāng)庫(kù),如果要移除它的話(huà)采用如下命令:
reprepro --ask-passphrase -Vb /var/www/apt remove bionic firefly-firmware
安裝 nginx 服務(wù)器:
sudo apt-get install nginx
修改nginx的配置文件 /etc/nginx/sites-available/default
為:
server { listen 80 default_server; listen [::]:80 default_server; root /var/www/apt; //本地包倉(cāng)庫(kù)的路徑 access_log /var/log/nginx/repo.access.log; error_log /var/log/nginx/repo.error.log; location ~ /(db|conf) { deny all; return 404; } }
重啟 nginx 服務(wù)器:
sudo service nginx restart
在客戶(hù)端開(kāi)發(fā)板中,首先要添加本地包倉(cāng)庫(kù)的源,在目錄 /etc/apt/sources.list.d
下添加一個(gè)新的配置文件 bionic.list
,內(nèi)容如下:
deb http://192.168.31.106 bionic main
IP 地址是服務(wù)器地址, bionic
是倉(cāng)庫(kù)發(fā)布代碼名, main
是組件名。
從服務(wù)器中獲取并添加 GPG 密匙:
wget -O - http://192.168.31.106/key/deb.gpg.key | apt-key add -
更新后即可安裝自定義軟件源里的 firefly-firmware_1.0_arm64
包:
root@firefly:/home/firefly# apt-get update Hit:1 http://192.168.31.106 bionic InRelease Hit:2 http://wiki.t-firefly.com/firefly-rk3399-repo bionic InRelease Hit:3 http://ports.ubuntu.com/ubuntu-ports bionic InRelease Hit:4 http://archive.canonical.com/ubuntu bionic InRelease Hit:5 http://ports.ubuntu.com/ubuntu-ports bionic-updates InRelease Hit:6 http://ports.ubuntu.com/ubuntu-ports bionic-backports InRelease Hit:7 http://ports.ubuntu.com/ubuntu-ports bionic-security InRelease Reading package lists... Done root@firefly:/home/firefly# apt-get install firefly-firmware Reading package lists... Done Building dependency tree Reading state information... Done The following package was automatically installed and is no longer required: libllvm6.0 Use 'apt autoremove' to remove it. The following NEW packages will be installed: firefly-firmware 0 upgraded, 1 newly installed, 0 to remove and 3 not upgraded. Need to get 0 B/6982 kB of archives. After this operation, 1024 B of additional disk space will be used. Selecting previously unselected package firefly-firmware. (Reading database ... 117088 files and directories currently installed.) Preparing to unpack .../firefly-firmware_1.0_arm64.deb ... Unpacking firefly-firmware (1.0) ... Setting up firefly-firmware (1.0) ... -----------uboot updating------------ 8192+0 records in 8192+0 records out 4194304 bytes (4.2 MB, 4.0 MiB) copied, 0.437281 s, 9.6 MB/s -----------trust updating------------ 8192+0 records in 8192+0 records out 4194304 bytes (4.2 MB, 4.0 MiB) copied, 0.565762 s, 7.4 MB/s -----------kernel updating------------ 39752+0 records in 39752+0 records out 20353024 bytes (20 MB, 19 MiB) copied, 0.1702 s, 120 MB/s
可以看到安裝過(guò)程中執(zhí)行了 deb 包中的 poinst
腳本。安裝完成后,重啟開(kāi)發(fā)板,更新完成。
在 /usr/share
目錄中還可以看到 kernel
和 uboot
目錄,分別存放了 boot.img
,uboot.img
和 trust.img
。
注意事項(xiàng)
-
在制作 deb 包中,與
DEBIAN
同級(jí)的目錄視為根目錄,即放在與DEBIAN
同目錄下的文件,在客戶(hù)端安裝 deb 包后,可以在客戶(hù)端的根目錄下找到; -
deb 包中的文件和腳本,用戶(hù)要根據(jù)自己的實(shí)際情況做調(diào)整;
-
每次在倉(cāng)庫(kù)中修改了配置文件后,都要重新導(dǎo)入倉(cāng)庫(kù)目錄樹(shù) ;
-
nginx 服務(wù)器配置中,
root
參數(shù)配置的是倉(cāng)庫(kù)的地址,請(qǐng)用戶(hù)根據(jù)自己的實(shí)際情況修改; -
客戶(hù)端添加的新下載源的文件時(shí),注意核對(duì)正確的服務(wù)器地址,包倉(cāng)庫(kù)代碼名和組件名。注意客戶(hù)端要連通服務(wù)器;
-
客戶(hù)端要用
apt-key add
命令添加 GPG 密匙之后,才可以獲取本地的倉(cāng)庫(kù)的信息。
distcc
是個(gè)通過(guò)網(wǎng)絡(luò)上的若干臺(tái)機(jī)器用來(lái)分布式編譯 C、C++、Objective-C 或 Objective-C++ 代碼的程序。distcc
不要求所有的機(jī)器共享文件系統(tǒng),有同步的時(shí)鐘,或者安裝有同樣的庫(kù)和頭文件,只要作為服務(wù)器的機(jī)器有合適的編譯工具即可進(jìn)行編譯。本例在兩塊 Firefly-RK3399 開(kāi)發(fā)板 (arm64) 和一臺(tái) PC 機(jī) (x86_64) 上利用 Docker 技術(shù)來(lái)布署 distcc 分布式編譯服務(wù),進(jìn)而實(shí)現(xiàn)在其中一塊 Firefly-RK3399 開(kāi)發(fā)板上利用 distcc 的分布式編譯特性來(lái)加速內(nèi)核的編譯過(guò)程。
-
兩塊 Firefly-RK3399 開(kāi)發(fā)板;
-
路由器、網(wǎng)線(xiàn);
-
PC 機(jī)。
將兩塊開(kāi)發(fā)板和 PC 機(jī)都連接到同一個(gè)局域網(wǎng)內(nèi)。連接好后對(duì)應(yīng)的 IP 地址別是:
-
PC 機(jī):192.168.1.100
-
開(kāi)發(fā)板 A:192.168.1.101
-
開(kāi)發(fā)板 B:192.168.1.102
使用腳本安裝 Docker :
wget -qO- https://get.docker.com/ | sh
為了可以使當(dāng)前普通用戶(hù)可以執(zhí)行 docker 相關(guān)命令,需要將當(dāng)前用戶(hù)添加到 dokcer 用戶(hù)組中:
sudo groupadd docker #添加 docker 用戶(hù)組 sudo gpasswd -a $USER docker #將當(dāng)前用戶(hù)添加到 docker 用戶(hù)組中 newgrp docker #更新 docker 用戶(hù)組
啟動(dòng) Docker 后臺(tái)服務(wù):
sudo service docker start
新建一個(gè) Dockerfile_distcc.x86_64
文件。其文件內(nèi)容如下:
FROM ubuntu:bionic MAINTAINER Firefly <service@t-firefly.com> ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update \ && apt-get install -y --no-install-recommends --no-install-suggests\ gcc-aarch64-linux-gnu distcc\ && apt-get clean \ && rm -rf /var/lib/apt/lists RUN ln -s aarch64-linux-gnu-gcc /usr/bin/gcc &&\ ln -s aarch64-linux-gnu-gcc /usr/bin/cc EXPOSE 3632 ENTRYPOINT ["/usr/bin/distccd"] CMD ["--no-detach" , "--log-stderr" , "--log-level", "debug", "--allow" , "0.0.0.0/0"]
生成 Docker 鏡像:
docker build -t distcc_server:x86_64 -f Dockerfile_distcc.x86_64 .
可以用命令 docker images
查看生成的 Docker 鏡像:
docker images REPOSITORY TAG IMAGE ID CREATED SIZE distcc_server x86_64 138c0b7e3801 9 minutes ago 66.1MB
用新建的鏡像啟動(dòng) Docker 容器,在主機(jī)網(wǎng)絡(luò)的 3632 TCP 端口提供 distcc 服務(wù):
docker run -d -p 3632:3632 distcc_server:x86_64
用命令 docker ps
可以查看正在運(yùn)行中的容器:
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fa468d068185 distcc_server:x86_64 "/usr/bin/distccd --…" 9 minutes ago Up 9 minutes 0.0.0.0:3632->3632/tcp epic_chatterjee
Firefly-RK3399 內(nèi)核默認(rèn)是不支持 Docker 的,需要進(jìn)行相關(guān)內(nèi)核的配置??梢栽?Firefly Github 中查看修改后的 /kernel/arch/arm64/configs/firefly_linux_defconfig
文件。
修改好后編譯內(nèi)核并更新到所有用到的開(kāi)發(fā)板。
內(nèi)核更新完成后,在開(kāi)發(fā)板上使用腳本安裝 Docker :
apt-get update wget -qO- https://get.docker.com/ | sh
將當(dāng)前用戶(hù)添加到 dokcer 用戶(hù)組中:
sudo groupadd docker sudo gpasswd -a $USER docker newgrp docker #更新 docker
啟動(dòng) Docker 后臺(tái)服務(wù):
service docker start
新建 Dockerfile_distcc.arm64
文件,內(nèi)容如下:
FROM ubuntu:bionic MAINTAINER Firefly <service@t-firefly.com> ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update \ && apt-get install -y --no-install-recommends --no-install-suggests \ gcc distcc\ && apt-get clean \ && rm -rf /var/lib/apt/lists EXPOSE 3632 ENTRYPOINT ["/usr/bin/distccd"] CMD ["--no-detach" , "--log-stderr" , "--log-level", "debug", "--allow" , "0.0.0.0/0"]
生成 Docker 鏡像:
docker build -t distcc_server:arm64 -f Dockerfile_distcc.arm64 .
用新建的鏡像啟動(dòng) Docker 容器,在主機(jī)網(wǎng)絡(luò)的 3632 TCP 端口提供 distcc 服務(wù):
docker run -d -p 3632:3632 distcc_server:arm64
用 docker save
命令導(dǎo)出新建的鏡像:
docker save -o distcc_server.tar distcc_server:arm64
將生成的 distcc_server.tar
文件復(fù)制到另一塊開(kāi)發(fā)板上,然后導(dǎo)入鏡像:
docker load -i distcc_server.tar
導(dǎo)入鏡像后,在這個(gè)開(kāi)發(fā)板上也有了 distcc_server:arm64
鏡像,然后可以運(yùn)行一個(gè)容器:
docker run -d -p 3632:3632 distcc_server:arm64
提示: 用戶(hù)如果注冊(cè)了 Docker Hub 帳號(hào),可以用 docker push
推送鏡像到遠(yuǎn)程倉(cāng)庫(kù),在另一開(kāi)發(fā)板上用 docker pull
拉取遠(yuǎn)程倉(cāng)庫(kù)的鏡像。用戶(hù)可以自行了解相關(guān)操作。
到這里,三個(gè)機(jī)器都部署了分布式編譯環(huán)境??梢赃x擇任意一臺(tái)機(jī)器作為客戶(hù)端,剩下兩個(gè)機(jī)器作為服務(wù)器。這里選擇其中一個(gè)開(kāi)發(fā)板作為客戶(hù)端。
在客戶(hù)端中創(chuàng)建 Dockerfile_compile.arm64
文件,生成一個(gè)編譯內(nèi)核的 Docker 鏡像,文件內(nèi)容如下:
FROM ubuntu:bionic MAINTAINER Firefly <service@t-firefly.com> ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update \ && apt-get install -y --no-install-recommends --no-install-suggests \ bc make python sed libssl-dev binutils build-essential distcc\ liblz4-tool gcc \ && apt-get clean \ && rm -rf /var/lib/apt/lists
然后生成鏡像:
docker build -t compile:arm64 -f Dockerfile_compile.arm64 .
在啟動(dòng)容器前先將內(nèi)核文件拉到客戶(hù)端中。然后創(chuàng)建 /etc/distcc/hosts
文件,其內(nèi)容是列舉出所有提供 distcc 服務(wù)的機(jī)器的 IP 地址。內(nèi)容如下:
# As described in the distcc manpage, this file can be used for a global # list of available distcc hosts. # # The list from this file will only be used, if neither the # environment variable DISTCC_HOSTS, nor the file $HOME/.distcc/hosts # contains a valid list of hosts. # # Add a list of hostnames in one line, seperated by spaces, here. 192.168.1.100 192.168.1.101 193.168.1.102
為了測(cè)試結(jié)果更準(zhǔn)確,先清除客戶(hù)端開(kāi)發(fā)板上的緩存:
echo 3 > /proc/sys/vm/drop_caches
用 compile:arm64
鏡像啟動(dòng)一個(gè) Docker 容器,同時(shí)將主機(jī)當(dāng)前內(nèi)核目錄掛載到容器中的 /mnt
目錄,將主機(jī)的 /etc/distcc/hosts
文件掛載到容器的 /etc/distcc/hosts
中,并用參數(shù) -it
以交互模式啟動(dòng)容器:
docker run -it --rm -v $(pwd):/mnt -v /etc/distcc/hosts:/etc/distcc/hosts compile:arm64 /bin/bash root@f4415264351b:/# ls bin boot dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var root@f4415264351b:/# cd mnt/
進(jìn)入到容器中的 /mnt
目錄,然后開(kāi)始用 distcc 編譯內(nèi)核,加入 time
命令可以查看編譯命令執(zhí)行耗時(shí),CC
參數(shù)指明用 distcc
進(jìn)行編譯:
time make ARCH=arm64 rk3399-firefly.img -j32 CC="distcc"
注意: 如果用 PC 機(jī)作為客戶(hù)端,則需要用以下命令進(jìn)行編譯:
time make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- rk3399-firefly.img -j32 CC="distcc aarch64-linux-gnu-gcc"
編譯過(guò)程中,可以在用于編譯的容器內(nèi)新的窗口中用命令 distccmon-text 1
查看編譯情況:
distccmon-text 1 ... 15713 Compile perf_regs.c 192.168.1.101[0] 15327 Compile fork.c 192.168.1.101[2] 15119 Compile dma-mapping.c 192.168.1.101[3] 15552 Compile signal32.c 192.168.1.100[0] 15644 Compile open.c 192.168.1.100[2] 15112 Compile traps.c 192.168.1.100[3] 15670 Compile arm64ksyms.c 192.168.1.102[0] 15629 Compile mempool.c 192.168.1.102[2] 15606 Compile filemap.c 192.168.1.102[3] 15771 Preprocess localhost[0] 15573 Preprocess localhost[1] 15485 Preprocess localhost[2] ...
最后編譯命令完成后可以看到編譯所用時(shí)間:
real 15m44.809s user 16m0.029s sys 6m22.317s
下邊是單獨(dú)使用一塊開(kāi)發(fā)板進(jìn)行內(nèi)核編譯所耗費(fèi)的時(shí)間:
real 23m33.002s user 113m2.615s sys 9m29.348s
對(duì)比可見(jiàn),用采用 distcc 實(shí)現(xiàn)的分布式編譯可以有效提高編譯速度。
注意:
-
平臺(tái)不同,所需的編譯器也不同。如在 x86_64 平臺(tái)上,需要安裝對(duì)應(yīng)的交叉編譯工具
gcc-aarch64-linux-gnu
。在 arm64 平臺(tái)則只需要安裝gcc
編譯工具即可。用戶(hù)需要根據(jù)實(shí)際情況在對(duì)應(yīng)的Dockerfile
文件里指定安裝正確的工具。 -
如果用 PC 機(jī)做客戶(hù)端,則在用于編譯的容器中編譯內(nèi)核的時(shí)候,要用參數(shù)
CC="distcc aarch64-linux-gnu-gcc"
指明用aarch64-linux-gnu-gcc
交叉編譯工具編譯。
-
嵌入式主板
+關(guān)注
關(guān)注
7文章
6102瀏覽量
36308 -
安卓
+關(guān)注
關(guān)注
5文章
2155瀏覽量
58706 -
可制造性設(shè)計(jì)
+關(guān)注
關(guān)注
10文章
2065瀏覽量
16084 -
Firefly
+關(guān)注
關(guān)注
2文章
542瀏覽量
8406 -
華秋DFM
+關(guān)注
關(guān)注
20文章
3504瀏覽量
5493
發(fā)布評(píng)論請(qǐng)先 登錄
Firefly-RK3399 Android8.1固件,可調(diào)用神經(jīng)網(wǎng)絡(luò)API進(jìn)行硬件加速
講講怎么在Firefly RK3399上安裝Android系統(tǒng)
Firefly RK3399開(kāi)源板的雙目攝像頭數(shù)據(jù)采集方案
Firefly -RK3399電源適配器介紹

Firefly-RK3399--PWM介紹

Firefly-RK3399--LED 介紹

Firefly-RK3399--ADC開(kāi)發(fā)板介紹

Firefly-RK3399開(kāi)發(fā)板介紹

評(píng)論