色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Firefly-RK3399-編碼api介紹

firefly ? 來源:firefly ? 作者:firefly ? 2019-11-25 09:44 ? 次閱讀
Ubuntu 應用層支持
視頻硬件編解碼支持

Mpp是Rockchip為RK3399提供的一套視頻編解碼的api, 并且基于mpp,Rockchip提供了一套gstreamer的編解碼插件。用戶可以根據自己的需求,基于gstreamer來做視頻編解碼的應用,或者直接調用mpp,來實現硬件的編解碼加速。

Firefly 發布的Ubuntu 系統, 都已經提供了完整的gstremaer 和 mpp支持,并且提供了相應的demo,供用戶開發參考。

Gstreamer
  • Ubuntu 16.04 下,gstreamer 1.12 已經安裝在/opt/目錄下。

  • Ubuntu 18.04下, gstreamer 1.12 已經安裝到系統中。

/usr/local/bin/h264dec.sh 測試硬件H264解碼。

/usr/local/bin/h264enc.sh 測試硬件H264編碼。

用戶可以參照這兩個腳本,配置自己的gstreamer應用。

Mpp
  • Ubunut 系統下, mpp 相關dev包都已經安裝到系統中。

    /opt/mpp/下分別是mpp 編解碼的相關demo 和 源文件。

OpenGL-ES

RK3399 支持 OpenGL ES1.1/2.0/3.0/3.1。

Firefly 發布的Ubuntu 系統, 都已經提供了完整的OpenGL-ES支持。運行glmark2-es2可以測試openGL-ES支持。 如果要避免屏幕刷新率對測試結果的影響,可以在串口終端上使用以下命令測試。

# systemctl stop lightdm # export DISPLAY=:0 # Xorg & # glmark2-es2 –off-screen

在Chromium瀏覽器中, 在地址欄輸入:chrome://gpu可以查看chromium下硬件加速的支持。

Note:

  1. EGL 是用arm 平臺上OpenGL針對x window system的擴展,功能等效于x86下的glx庫。

  2. 由于Xorg使用的Driver modesettings 默認會加載libglx.so(禁用glx會導致某些通過檢測glx環境的應用啟動失敗), libglx.so會搜索系統中的dri實現庫。但是rk3399 Xorg 2D加速是直接基于DRM實現, 并未實現dri庫,所以啟動過程中,libglx.so會報告如下的錯誤 。

    (EE) AIGLX error: dlopen of /usr/lib/aarch64-linux-gnu/dri/rockchip_dri.so failed

    這個對系統運行沒有任何影響,不需要處理。

  3. 基于同樣的道理,某些應用啟動過程中,也會報告如下錯誤,不用處理,對應用的運行不會造成影響。

    libGL error: unable to load driver: rockchip_dri.so libGL error: driver pointer missing libGL error: failed to load driver: rockchip
  4. Firefly之前發布的某些版本的Ubuntu軟件,默認關閉了加載libglx.so,在某些情況下,運行某些應用程序會出現下述錯誤:

    GdkGLExt-WARNING **: Window system doesn't support OpenGL.

    修正的方法如下:

    刪除 /etc/X11/xorg.conf.d/20-modesetting.conf 中一下三行配置。

    Section "Module" Disable "glx" EndSection
OpenCL

Firefly發布的Ubuntu系統,已經添加了opencl1.2支持,可以運行系統內置的clinfo獲取平臺opencl相關參數

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) …
TensorFlow Lite

RK3399 支持神經網絡的GPU加速方案LinuxNN, Firefly發布的Ubuntu系統,已經添加了LinuxNN的支持。

在opt/tensorflowbin/下,運行test.sh, 即可測試MobileNet 模型圖像分類器的 Demo和MobileNet-SSD 模型的目標檢測 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 發布的 Ubuntu 系統,如果需要默認對系統的顯示方向做旋轉,可以在

/etc/default/xrandr 中修改對應的顯示設備的方向即可。

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

對于配有觸摸屏的平臺,如果需要對觸摸屏的方向做旋轉,可以在/etc/X11/xorg.conf.d/05-gslX680.conf中修改SwapAxes / InvertX / InvertY三個值。

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 系統中自帶屏幕鍵盤,可以在菜單欄中點擊打開:

聲音配置

開發板一般都有2個或以上的音頻設備。常見的是耳機和 HDMI 這兩個設備的音頻輸出。下面是音頻設置的例子,供用戶參考。

從命令行指定音頻設備

系統自帶的音頻文件在 /usr/share/sound/alsa/ 目錄中,播放前請先查看聲卡設備:

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 的設備0對應的是耳機口,card1 的設備0對應的是 HDMI。一般播放音頻命令是 aplay -Dhw:0,0 Fornt_Center.wav,但系統自帶的音頻文件是單聲道的,所以為了防止播放失敗,可以按照下面的命令進行播放:

#選擇耳機口輸出音頻文件 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
在圖形界面中選擇音頻設備

在圖形界面中,播放準備好的音頻文件,然后點擊聲音圖標,打開 Sound Setting,選擇到 Configuration 。可以看到兩個聲卡設備,例如設置為 HDMI 輸出音頻,則把 HDMI 的聲卡設備選擇為 Output,另一個聲卡設置為 Off。(如果 HDMI 無聲或者聲音小,可以試試按 HDMI 屏上的物理按鍵調高音量)

開機啟動應用程序

在系統中,可以根據用戶需求自行設置應用程序開機自動啟動。

在系統菜單欄中依次選擇:Preferences -> Default applications for LXSession,打開設置界面。

在設置界面的 Launching applocations 一欄中可以設置應用默認的打開方式:

Autostart 一欄中就可以選擇用戶需要開機啟動的應用。例如藍牙默認是開機不啟動的,如果需要讓它開機自動啟動,就把 Blueman Applet 的勾打上,就可以實現開機自動啟動藍牙:

ABD 調試

ADB,全稱 Android Debug Bridge,是 Android 的命令行調試工具,可以完成多種功能,如跟蹤系統日志,上傳下載文件,安裝應用等。以 Firefly-RK3399 為例,為了在 Ubuntu 系統也能使用 ADB 工具進行調試,我們移植了 ADB 服務。但由于并非 Android 系統,很多 ADB 命令類似 adb logcatadb install 等不能使用,僅作為普通的調試輔助工具,可以進行 shell 交互、上傳下載文件等操作。同樣的網絡遠程 ADB 調試也不能使用。

下載 ADB

在 Ubuntu 系統中,執行:

sudo apt-get install android-tools-adb
內核配置

在內核目錄下,打開內核配置選項菜單:

make firefly_linux_defconfig make menuconfig

進入內核配置菜單后依次選擇:Device Drivers -> USB Support -> USB Gadget Support

USB Gadget Driver 選項中選擇到 USB functions configurable through configfs

同時再選擇上 Function filesystem (FunctionFS)

<*> USB Gadget Drivers (USB functions configurable through configfs) ---> USB functions configurable through configfs [*] Function filesystem (FunctionFS)

接著在 kernel 目錄下編譯內核:

make rk3399-firefly.img -j12

編譯完成后將內核燒錄到開發板中,燒錄過程請參考維基教程:升級固件中的分區鏡像燒寫部分。

ADB 連接

安裝了 ADB 后,用 Micro USB OTG 線連接開發板和 PC 機。然后通過命令 adb devices 查看是否有設備連接:

firefly@Desktop:~$ adb devices List of devices attached 0123456789ABCDEF device

從返回的信息可以看到已經查找到了設備,表明設備已經成功連接。

設備連接成功后,輸入命令 adb shell 即可進入命令行模式:

firefly@Desktop:~$ adb shell #

此狀態下是看不到命令行當前的路徑,同時 Tab 鍵補全功能失效,需要進入一個用戶中才可以正常操作。

firefly@Desktop:~$ adb shell # su firefly To run a command as administrator (user "root"), use "sudo
". See "man sudo_root" for details. firefly@firefly:/$ #到這里命令行就可以正常使用了

用戶也可以使用命令 adb shell /bin/bash,也可以進入正常的命令行模式。

可以輸入 adb help 查看命令行幫助信息,注意并不是所有命令都可以使用,幫助信息只做參考。

串口

開發板上的串口分兩種,一種是普通串口另外一種是通過轉換芯片把SPI轉換而成的串口。轉換而成的串口和普通串口功能完全一致但是需要注意它們的設備文件名是不一樣的。下面是兩者的區別:

//普通串口 root@firefly:~# ls /dev/ttyS* ttyS0 ttyS1 ttyS2 ttyS3 //SPI轉串口 root@firefly:~# ls /dev/ttysWK* ttysWK0 ttysWK1 ttysWK2 ttysWK3
設置波特率

ttyS4 為例,查看串口波特率命令:

root@firefly:~# stty -F /dev/ttyS4 speed 9600 baud; line = 0; -brkint -imaxbel

設置波特率命令:

//設置波特率為115200 root@firefly:~# stty -F /dev/ttyS4 ospeed 115200 ispeed 115200 cs8 //查看確認是否已經修改 root@firefly:~# stty -F /dev/ttyS4 speed 115200 baud; line = 0; -brkint -imaxbel root@firefly:~#
關閉回顯

在做環回收發測試的時候回顯功能會影響到我們的測試結果,所以在環回測試或者其他特殊情況下需要關閉回顯。以下是關閉回顯的命令:

//關閉回顯示 root@firefly:~# stty -F /dev/ttyS4 -echo -echoe -echok //查看所有功能的配置,檢查是否已經關閉。“-”號代表該功能已經關閉 root@firefly:~# stty -F /dev/ttyS4 -a | grep echo isig icanon iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc
發送接收原始數據

在實際應用中實際發送數據和我們希望發送的數據可能存在差別,例如多了回車或者其他特殊字符。利用 stty 可以把發送接收設置成 raw 模式確保發送接收的是原始數據,以下是設置命令:

root@firefly:~# stty -F /dev/ttyS4 raw
工作模式

串口有 2 種工作模式分別是中斷模式和 DMA 模式。

中斷模式

內核默認把串口配置成中斷模式所以不需要做任何修改。中斷模式下傳輸速率比較快但是在傳大量數據的時候很容易丟包或者出錯,所以當數據量比較大的時候請不要使用中斷模式。

DMA 模式

DMA 模式主要是傳輸大量數據的時候使用。內核會為串口提供一個緩存空間接收數據來盡量降低串口傳輸的丟包率。

注意: 緩存空間限默認大小為 8K 如果一次傳輸超過緩存大小就會丟包,所以使用 DMA 模式的話需要發送端需要分包發送。

設備樹文件配置

&uart4 { status = "okay"; + dmas = <&dmac_peri 8>, <&dmac_peri 9>; + dma-names = "tx", "rx"; };

DMA 模式并不能提高傳輸速率,相反因為需要緩存,傳輸速率會有所下降,所以如果不是需要傳輸大量數據的話不要使用 DMA 模式。

流控

不管是中斷模式還有 DMA 模式都無法保證數據傳輸萬無一失,因為長時間傳輸大量數據的時候 DDRCPU 變頻或者占用率過高都可能導致上層處理數據不及時導致丟包,這個時候就需要是用流控了。流控分兩種,一種是軟件流控另一種為硬件流控,下面只介紹硬件流控的使用。

硬件支持

硬件流控需要有硬件支持,開發板的串口 CTXRTX 腳需要和設備相連。

注意: 開發板不是所有串口都支持硬件流控,請先從原理圖上確認硬件是否支持

設備樹文件配置

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"; };

應用層設置

上層也需要打開流控的設置,這里介紹 stty 如何打開流控如果你使用的是其他應用程序請從應用中打開流控。

//打開流控 root@firefly:~# stty -F /dev/ttyS4 crtscts //檢測流控是否打開,“-”號代表該功能已經關閉 root@firefly:~# stty -F /dev/ttyS4 -a | grep crtscts -parenb -parodd -cmspar cs8 hupcl -cstopb cread clocal crtscts
MIPI 攝像頭 (OV13850)

帶有 MIPI CSI 接口的 RK3399 板子都添加了雙 MIPI 攝像頭 OV13850 的支持,應用中也添加了攝像頭的例子。下面介紹一下相關配置。

設備樹文件配置

rk3399-firefly-aiojd4.dts 為例,這些都是攝像頭需要打開的配置。由于內核已經添加了雙 MIPI 攝像頭的支持,所以這里配置了兩個攝像頭,如果只使用一個攝像只需要打開其中一個攝像頭就可以了。

//電源管理 &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 底板,可能需要修改相應的 GPIO 屬性。

調試

在運行腳本之前先確認一下 OV13850 設備是否注冊成功,下面是成功的內核日志:

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 下應該生成相關設備文件:

root@firefly:~# ls /dev/video //MIPI 攝像頭1 video0 video1 video2 video3 //MIPI 攝像頭2 video4 video5 video6 video7

注意: 同理,如果只使用一個攝像頭,只需要注冊一個攝像頭設備就可以了。

測試

在官方提供的 Ubuntu 系統中已經添加了攝像頭測試腳本 /usr/local/bin/dual-camera-rkisp.sh,其內容為:

#!/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

運行腳本即可,結果如圖所示:

USB 以太網

USB 以太網,主要實現的是將開發板的 OTG 接口做外設模式,模擬成一個網絡接口,然后主機通過 USB 連接開發板并通過開發板訪問互聯網。以下是基于 Firefly-RK3399 開發板進行的具體操作。

操作環境:

  • Ubuntu 系統的 PC 機

  • Firefly-RK3399 開發板

內核設置

在內核目錄下,打開內核配置選項菜單:

make firefly_linux_defconfig make menuconfig

進入內核配置菜單后依次選擇:Device Drivers -> USB Support -> USB Gadget Support

USB Gadget Driver 設置成編譯成模塊,然后可以在下邊找到 Ethernet Gadget (with CDC Ethernet support) 選項,同樣選擇編譯成模塊。同時要選擇上 RNDIS support

<M> USB Gadget Drivers <M> USB functions configurable through configfs <M> Ethernet Gadget (with CDC Ethernet support) [*] RNDIS support (NEW)

接著在 kernel 目錄下編譯內核:

make rk3399-firefly.img -j12

編譯完成后將內核燒錄到開發板中,燒錄過程請參考維基教程:升級固件中的分區鏡像燒寫部分。然后將內核目錄下生成的下列模塊復制到開發板中:

  • 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

然后在開發板上,依次加載上述模塊:

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.kou_ether.ko,后面的模塊才可以加載進去。

IP 地址設置

用數據線連接 PC 機和開發板的 OTG 接口,在 PC 機中執行 lsusb 命令可以查看到 USB 以太網設備,即說明連接成功。

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 網卡設備。

開發板插入網線,使開發板可以連接外網。

  • 在開發板中 IP 的設置:

輸入執行 ifconfig -a 命令,可以查看到以下信息:

root@firefly:~# ifconfig -a # eth0 是有線網卡 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 網卡 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 網卡自定義一個適當的 IP:

注意要設置 usb0 的 IP 和有線網卡 eth0 的 IP 不在同一網段!!

ifconfig usb0 192.168.1.101
  • 在 PC 機中 IP 的設置:

# 先查看 USB 虛擬網卡 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 (以太網) 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 ... # 設置 USB 網卡的 IP 地址和開發板的 usb0 的 IP 地址在同一網段 firefly@Desktop:~$ sudo ifconfig enp0s20u2i1 192.168.1.100 #設置默認網關:要設置為開發板 usb0 的 ip 地址,因為后面要通過 usb0 來進行流量的轉發 firefly@Desktop:~$ sudo route add default gw 192.168.1.101

設置完開發板和 PC 機的 IP 后,互相是可以 ping 通的,PC 機也可以用 ssh 命令登錄到開發板。

網絡共享實現 PC 機上網

在開發板上:首先打開 IPv4 的轉發功能:

echo 1 > /proc/sys/net/ipv4/ip_forward

如果希望每次重啟開發板后都自動打開轉發功能,請直接修改 /etc/sysctl.conf 文件的 net.ipv4.ip_forward 值為1。修改文件參數后要執行 sysctl -p 命令重新載入 /etc/sysctl.conf 文件,使 IPv4 轉發功能生效。

添加規則進行流量轉發:

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 168.168.100.48

現在 PC 主機就可以訪問網絡了。如果 PC 機可以 ping 通開發板的 usb0 和 eth0,但是無法上外網,則需要修改 PC 機的 DNS,在 /etc/resolv.conf 中做以下添加:

nameserver 8.8.8.8 nameserver 8.8.4.4

配置過程中要注意以下幾點:

  • 對應好上述步驟中自己設備上的各個 IP 地址,注意開發板上的 USB 虛擬網卡 IP 和有線網絡 IP 不在同一網段;

  • PC 機虛擬 USB 網卡的網關要設置為開發板虛擬 USB 網卡的 IP 地址;

  • 開發板上的虛擬網卡 IP 地址、IP 轉發功能、流量轉發規則等設置會在設備重啟后恢復,用戶可以自行查找資料如何開機自動設置這些配置。

外部存儲設備 rootfs

根文件系統除了可以使用在內部的 eMMC 中的,還可以使用外部存儲設備的根文件系統,如 SD 卡,U 盤等。以下是以 SD 卡為例,在 Firefly-RK3399 開發板上實現掛載外部存儲設備的根文件系統。

在 SD 卡上建立分區

在 PC 機上插入 SD 卡,用 gdisk 工具分出一個裝載根文件系統的分區:

#用戶請用 `fdisk -l` 查詢 SD 卡設備名是什么,在用 gdisk 命令進入對應的設備 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 卡當前已有分區,由于使用的 SD 卡暫未創建分區,所以沒有查詢到分區信息 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 ------------------------------------------------------------------- #創建新的分區,請用戶根據自身實際情況創建合適的分區大小給根文件系統 Command (? for help): n #輸入 n 創建新分區 Partition number (1-128, default 1): 1 #輸入1創建第一個分區 First sector (34-15278046, default = 2048) or {+-}size{KMGTP}: #直接按回車,使用默認值 Last sector (2048-15278046, default = 15278046) or {+-}size{KMGTP}: +3G #創建分區大小為3G Current type is 'Linux filesystem' Hex code or GUID (L to show codes, Enter = 8300): #按回車使用默認值 Changed type of partition to 'Linux filesystem' ------------------------------------------------------------------- #創建完成后,輸入 i,可以查看分區的 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 #使用的是該分區的 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.

把新創建的分區進行格式化。

# 注意 sdb1 表示 SD 卡對應分區設備名,請用戶根據實際情況填入 sudo mkfs.ext4 /dev/sdb1

格式化完成后,使用 dd 命令,將制作好的根文件系統燒寫到 SD 卡剛新建的分區中。(根文件系統的制作可以參考Ubuntu 根文件系統的制作

# 用戶請根據實際情況填寫根文件系統鏡像的路徑和 SD 卡對應分區設備名 dd if=/rootfs_path/rootfs.img of=/dev/sdb1
掛載 SD 卡根文件系統

首先要修改設備樹文件,打開對應的 dts 文件,在根節點下重寫 chosen 節點下的 bootargs 參數的 root 值為寫入了根文件系統的 SD 卡分區的 unique GUID:

#將 root 的值改為獲取到的 unique GUID 值的前12位 chosen { bootargs = "earlycon=uart8250,mmio32,0xff1a0000 swiotlb=1 console=ttyFIQ0 rw root=PARTUUID=6278AF5D-BC6B rootfstype=ext4 rootwait"; };

修改完成后編譯并燒錄至開發板中。

SD 卡的根文件系統燒錄完成后,插入開發板的 TF 卡槽中,開機即可進入到 SD 的根文件系統中。

注意事項:

  • 在操作前請注意備份 U 盤或者 SD 卡內的重要文件,避免丟失;

  • 操作時請確認自己的 SD 卡對應的設備名;

  • dts 文件中 root 參數的值使用的是 unique GUID,記下前12位即可。用戶也可以根據 gdisk 的幫助信息自行修改這個值。

網絡啟動

網絡啟動,是用 TFTP 在服務器下載內核、dtb 文件到目標機的內存中,同時可以用 NFS 掛載網絡根文件系統到目標機上,實現目標機的無盤啟動。以下基于 Firefly-RK3399 作出一個示例,提供用戶參考。

準備工作:

  • Firefly-RK3399 開發板;

  • 路由器、網線;

  • 安裝有 NFS 和 TFTP 的服務器;

  • 一份制作好的根文件系統。

注:示例中使用的是 Ubuntu 系統的 PC 機作為服務器,通過路由器和網線實現與開發板的連接。用戶可以根據自己的實際情況作調整,但如果是 PC 機直連開發板,請使用交叉網線。請確保服務器和目標機在同一局域網內。

服務器部署

1、在服務器上部署 TFTP 服務:

安裝 TFTP 服務:

sudo apt-get install tftpd-hpa

創建 /tftpboot 目錄并賦予權限:

mkdir /tftpboot sudo chmod 777 /tftpboot

然后修改 TFTP 服務器的配置文件 /etc/default/tftpd-hpa,修改內容為:

# /etc/default/tftpd-hpa TFTP_USERNAME="tftp" TFTP_DIRECTORY="/tftpboot" #這個根據用戶實際的 tftp 目錄設置 TFTP_ADDRESS="0.0.0.0:69" TDTP_OPTIONS="-c -s -l"

退出修改后重啟 TFTP 服務器:

sudo service tftpd-hpa restart

/tftpboot 目錄中創建一個文件,測試 TFTP 服務是否可用:

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 服務器是可用的。

2、在服務器上部署 NFS 服務:

安裝 NFS 服務器:

sudo apt-get install nfs-kernel-server

創建共享目錄:

sudo mkdir /nfs sudo chmod 777 /nfs cd /nfs sudo mkdir rootfs sudo chmod 777 rootfs

然后將制作好的根文件系統復制到 /nfs/rootfs 目錄中。(根文件系統的制作可以參考:Ubuntu 根文件系統的制作

接著配置 NFS,在 /etc/exports 中添加共享目錄位置:

/nfs/rootfs *(rw,sync,no_root_squash,no_subtree_check)

共享的目錄根據用戶實際情況設置,其中的”*”代表的是所有用戶可訪問。

重啟 NFS 服務器:

sudo /etc/init.d/nfs-kernel-server restart

本地掛載共享目錄,測試 NFS 服務器是否可用:

sudo mount -t nfs 127.0.0.1:/nfs/rootfs/ /mnt

/mnt 目錄下查看到了與 /nfs/rootfs 一致的內容,則說明 NFS 服務器部署成功。然后可以解除掛載:

sudo umount /mnt
內核的配置

如果要做到掛載網絡根文件系統,需要在內核中做相關配置,并在 dts 中修改相關掛載根文件系統的配置。

首先進行內核配置,在內核目錄中執行 make menuconfig,選擇相關配置:

[*] 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 節點下的 bootargs 參數,選擇使用 NFS 掛載遠程根文件系統,內容如下。

chosen { bootargs = "earlycon=uart8250,mmio32,0xff1a0000 swiotlb=1 console=ttyFIQ0 root=/dev/nfs rootfstype=ext4 rootwait"; }; #主要是修改 root 的值,root=/dev/nfs 表示通過 NFS 掛載網絡根文件系統

編譯內核:

make ARCH=arm64 rk3399-firefly.img -j12

編譯完成后,將編譯好的內核文件 boot.imgrk3399-firefly.dtb 文件復制到 /tftpboot 目錄中:

cp boot.img /tftpboot cp arch/arm64/boot/dts/rockchip/rk3399-firefly.dtb /tftpboot

詳細說明可以參考內核目錄中的 kernel/Documentation/filesystems/nfs/nfsroot.txt

U-Boot設置

請先確保目標機網線已插入,接入到服務器的局域網內。

目標機啟動進入 U-Boot 命令行模式,設置以下參數:

=> setenv ipaddr 192.168.31.101 #設置目標機 IP 地址 => setenv serverip 192.168.31.106 #設置 serverip 為服務器 IP 地址 #設置從 TFTP 下載內核和 dtb 文件到相應地址,用戶請根據自己實際的目標機修改相應地址 => setenv bootcmd tftpboot 0x0027f800 boot.img \; tftpboot 0x08300000 rk3399-firefly.dtb \; bootm 0x0027f800 - 0x08300000 #設置掛載網絡根文件系統,IP 參數依次為:目標機 IP:服務器 IP:網關:網絡掩碼:設備名:off,可以更簡單的設置 ip=dhcp,通過 DHXP 自動分配 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 #如果不想每次開機都設置一遍,可以保存上面配置的變量 => saveenv Saving Environment to MMC... Writing to MMC(0)... done #啟動目標機 => 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 ... ...

在開機內核日志中可見:

[ 12.146297] VFS: Mounted root (nfs filesystem) on device 0:16.

說明已經掛載上了網絡根文件系統。

注意事項

  • 確保 TFTP 服務器、NFS 服務器可用;

  • 確保目標機先插入網線后在開機,且和服務器在同一局域網內,如果是直連目標機和服務器,請使用交叉網線;

  • 內核配置中,Root file system on NFS 依賴于 IP: kernel level autoconfiguration 選項,請先選擇 IP: kernel level autoconfiguration,之后才可以找到 Root file system on NFS 選項;

  • 在 U-Boot 命令行中,請確認 boot.img 燒錄地址和 dtb 文件燒錄地址。(提示:boot.img 的文件結構中,開頭有2k的頭文件,然后才是 kernel。所以在 TFTP 下載內核到目標機時,要下載到對應 kernel 地址減去0x0800的地址上);

  • 在設置掛載遠程根文件系統時,nfsroot=192.168.31.106:/nfs/rootfs,v3 中的 v3 代表 NFS 版本信息,請添加上以避免出現掛載不成功的問題。

在線更新內核和 U-Boot

本小節介紹了在線更新的一個簡單的流程。將內核、U-Boot 或者其他需要更新的文件打包成 deb 安裝包,然后導入到本地包倉庫,實現在開發板上下載并自動更新。僅供用戶參考。

準備 deb 安裝包

操作中需要升級內核和 U-Boot,事先已經準備好了修改好的相關文件:uboot.imgtrust.imgboot.img

deb 是 Debian Linux 的軟件包格式,打包最關鍵的是在 DEBIAN 目錄下創建一個 control 文件。首先創建 deb 工作目錄,然后在 deb 目錄中創建相應的目錄和文件:

mkdir deb cd deb mkdir firefly-firmware #創建 firefly-firmware 目錄 cd firefly-firmware mkdir DEBIAN #創建 DEBIAN 目錄,這個目錄是必須要有的。 mkdir -p usr/share/{kernel,uboot} mv ~/boot.img ~/deb/firefly-firmware/usr/share/kernel #將相應文件放到相應的目錄 mv ~/uboot.img ~/deb/firefly-firmware/usr/share/uboot mv ~/trust.img ~/deb/firefly-firmware/usr/share/uboot

DEBIAN 目錄下存放的文件是 deb 包安裝的控制文件以及相應的腳本文件。

DEBIAN 目錄下創建控制文件 control 和腳本文件 postinst

control 文件內容如下,用于記錄軟件標識,版本號,平臺,依賴信息等數據。

Package: firefly-firmware #文件目錄名 Version: 1.0 #版本號 Architecture: arm64 #架構 Maintainer: neg #維護人員,自定義即可 Installed-Size: 1 Section: test Priority: optional Descriptionon: This is a deb test

postinst 文件內容如下,就是將需要更新的內核和 U-Boot 文件用 dd 命令寫進對應分區的腳本:

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

說明:postinst 腳本,是在解包數據后運行的腳本,對應的還有:

  • preinst:在解包數據前運行的腳本;

  • prerm:卸載時,在刪除文件之前運行的腳本;

  • postrm:在刪除文件之后運行的腳本;

其他相關知識點用戶可以自行了解。這里只用到了 preinst 腳本。

以下是創建好的目錄樹:

deb └── firefly-firmware ├── DEBIAN │ ├── control │ └── postinst └── usr └── share ├── kernel │ └── boot.img └── uboot ├── trust.img └── uboot.img

進入 deb 目錄,用 dpkg 命令生成 deb 包:

dpkg -b firefly-firmware firefly-firmware_1.0_arm64.deb

生成 deb 包時,一般按照這種規范進行命名:package_version-reversion_arch.deb

創建本地倉庫

首先安裝需要的包:

sudo apt-get install reprepro gnupg

然后用 GnuPG 工具生成一個 GPG 密匙,執行命令后請根據提示操作:

gpg --gen-key

執行 sudo gpg --list-keys 可以查看剛剛生成的密匙信息:

sudo gpg --list-keys gpg: WARNING: unsafe ownership on homedir '/home/firefly/.gnupg' gpg: 正在檢查信任度數據庫 gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: 深度:0 有效性: 4 已簽名: 0 信任度:0-,0q,0n,0m,0f,4u gpg: 下次信任度數據庫檢查將于 2021-05-29 進行 /home/firefly/.gnupg/pubring.kbx -------------------------------- pub rsa3072 2019-05-31 [SC] [有效至:2021-05-30] BCB65788541D632C057E696B8CBC526C05417B76 uid [ 絕對 ] firefly sub rsa3072 2019-05-31 [E] [有效至:2021-05-30]

接下來創建包倉庫,首先創建目錄:

cd /var/www mkdir apt #包倉庫目錄 mkdir -p ./apt/incoming mkdir -p ./apt/conf mkdir -p ./apt/key

把前面生成的密匙導出到倉庫文件夾,請用戶對應好自己創建的用戶名和郵箱地址。

gpg --armor --export firefly firefly@t-chip.com > /var/www/apt/key/deb.gpg.key

conf 目錄下創建 distributions 文件,其內容如下:

Origin: Neg #你的名字 Label: Mian #庫的名字 Suite: stable #(stable 或 unstable) Codename: bionic #發布代碼名,可自定義 Version: 1.0 #發布版本 Architectures: arm64 #架構 Components: main #組件名,如main,universe等 Description: Deb source test #相關描述 SignWith: BCB65788541D632C057E696B8CBC526C05417B76 #上面步驟中生成的 GPG 密匙

建立倉庫樹:

reprepro --ask-passphrase -Vb /var/www/apt export

將第2步做好的 deb 包加入到倉庫中:

reprepro --ask-passphrase -Vb /var/www/apt includedeb bionic ~/deb/firefly-firmware_1.0_arm64.deb

可以查看庫中添加的文件:

root@Desktop:~# reprepro -b /var/www/apt/ list bionic bionic|main|arm64: firefly-firmware 1.0

你的包已經加入了倉庫,如果要移除它的話采用如下命令:

reprepro --ask-passphrase -Vb /var/www/apt remove bionic firefly-firmware

安裝 nginx 服務器:

sudo apt-get install nginx

修改nginx的配置文件 /etc/nginx/sites-available/default 為:

server { listen 80 default_server; listen [::]:80 default_server; root /var/www/apt; //本地包倉庫的路徑 access_log /var/log/nginx/repo.access.log; error_log /var/log/nginx/repo.error.log; location ~ /(db|conf) { deny all; return 404; } }

重啟 nginx 服務器:

sudo service nginx restart
客戶端更新安裝

在客戶端開發板中,首先要添加本地包倉庫的源,在目錄 /etc/apt/sources.list.d 下添加一個新的配置文件 bionic.list,內容如下:

deb http://192.168.31.106 bionic main

IP 地址是服務器地址, bionic 是倉庫發布代碼名, main 是組件名。

從服務器中獲取并添加 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

可以看到安裝過程中執行了 deb 包中的 poinst 腳本。安裝完成后,重啟開發板,更新完成。

/usr/share 目錄中還可以看到 kerneluboot 目錄,分別存放了 boot.imguboot.imgtrust.img

注意事項

  • 在制作 deb 包中,與 DEBIAN 同級的目錄視為根目錄,即放在與 DEBIAN 同目錄下的文件,在客戶端安裝 deb 包后,可以在客戶端的根目錄下找到;

  • deb 包中的文件和腳本,用戶要根據自己的實際情況做調整;

  • 每次在倉庫中修改了配置文件后,都要重新導入倉庫目錄樹 ;

  • nginx 服務器配置中,root 參數配置的是倉庫的地址,請用戶根據自己的實際情況修改;

  • 客戶端添加的新下載源的文件時,注意核對正確的服務器地址,包倉庫代碼名和組件名。注意客戶端要連通服務器;

  • 客戶端要用 apt-key add 命令添加 GPG 密匙之后,才可以獲取本地的倉庫的信息。

用Docker搭建分布式編譯環境

distcc 是個通過網絡上的若干臺機器用來分布式編譯 C、C++、Objective-C 或 Objective-C++ 代碼的程序。distcc 不要求所有的機器共享文件系統,有同步的時鐘,或者安裝有同樣的庫和頭文件,只要作為服務器的機器有合適的編譯工具即可進行編譯。本例在兩塊 Firefly-RK3399 開發板 (arm64) 和一臺 PC 機 (x86_64) 上利用 Docker 技術來布署 distcc 分布式編譯服務,進而實現在其中一塊 Firefly-RK3399 開發板上利用 distcc 的分布式編譯特性來加速內核的編譯過程。

準備工作
  • 兩塊 Firefly-RK3399 開發板;

  • 路由器、網線;

  • PC 機。

將兩塊開發板和 PC 機都連接到同一個局域網內。連接好后對應的 IP 地址別是:

  • PC 機:192.168.1.100

  • 開發板 A:192.168.1.101

  • 開發板 B:192.168.1.102

PC 機部署 Docker

使用腳本安裝 Docker :

wget -qO- https://get.docker.com/ | sh

為了可以使當前普通用戶可以執行 docker 相關命令,需要將當前用戶添加到 dokcer 用戶組中:

sudo groupadd docker #添加 docker 用戶組 sudo gpasswd -a $USER docker #將當前用戶添加到 docker 用戶組中 newgrp docker #更新 docker 用戶組

啟動 Docker 后臺服務:

sudo service docker start

新建一個 Dockerfile_distcc.x86_64 文件。其文件內容如下:

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

用新建的鏡像啟動 Docker 容器,在主機網絡的 3632 TCP 端口提供 distcc 服務:

docker run -d -p 3632:3632 distcc_server:x86_64

用命令 docker ps 可以查看正在運行中的容器:

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
開發板部署 Docker

Firefly-RK3399 內核默認是不支持 Docker 的,需要進行相關內核的配置。可以在 Firefly Github 中查看修改后的 /kernel/arch/arm64/configs/firefly_linux_defconfig 文件。

修改好后編譯內核并更新到所有用到的開發板。

內核更新完成后,在開發板上使用腳本安裝 Docker :

apt-get update wget -qO- https://get.docker.com/ | sh

將當前用戶添加到 dokcer 用戶組中:

sudo groupadd docker sudo gpasswd -a $USER docker newgrp docker #更新 docker

啟動 Docker 后臺服務:

service docker start

新建 Dockerfile_distcc.arm64 文件,內容如下:

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 .

用新建的鏡像啟動 Docker 容器,在主機網絡的 3632 TCP 端口提供 distcc 服務:

docker run -d -p 3632:3632 distcc_server:arm64

docker save 命令導出新建的鏡像:

docker save -o distcc_server.tar distcc_server:arm64

將生成的 distcc_server.tar 文件復制到另一塊開發板上,然后導入鏡像:

docker load -i distcc_server.tar

導入鏡像后,在這個開發板上也有了 distcc_server:arm64 鏡像,然后可以運行一個容器:

docker run -d -p 3632:3632 distcc_server:arm64

提示: 用戶如果注冊了 Docker Hub 帳號,可以用 docker push 推送鏡像到遠程倉庫,在另一開發板上用 docker pull 拉取遠程倉庫的鏡像。用戶可以自行了解相關操作。

客戶端用 distcc 編譯內核

到這里,三個機器都部署了分布式編譯環境。可以選擇任意一臺機器作為客戶端,剩下兩個機器作為服務器。這里選擇其中一個開發板作為客戶端。

在客戶端中創建 Dockerfile_compile.arm64 文件,生成一個編譯內核的 Docker 鏡像,文件內容如下:

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 .

在啟動容器前先將內核文件拉到客戶端中。然后創建 /etc/distcc/hosts 文件,其內容是列舉出所有提供 distcc 服務的機器的 IP 地址。內容如下:

# 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

為了測試結果更準確,先清除客戶端開發板上的緩存:

echo 3 > /proc/sys/vm/drop_caches

compile:arm64 鏡像啟動一個 Docker 容器,同時將主機當前內核目錄掛載到容器中的 /mnt 目錄,將主機的 /etc/distcc/hosts 文件掛載到容器的 /etc/distcc/hosts 中,并用參數 -it 以交互模式啟動容器:

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/

進入到容器中的 /mnt 目錄,然后開始用 distcc 編譯內核,加入 time 命令可以查看編譯命令執行耗時,CC 參數指明用 distcc 進行編譯:

time make ARCH=arm64 rk3399-firefly.img -j32 CC="distcc"

注意: 如果用 PC 機作為客戶端,則需要用以下命令進行編譯:

time make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- rk3399-firefly.img -j32 CC="distcc aarch64-linux-gnu-gcc"

編譯過程中,可以在用于編譯的容器內新的窗口中用命令 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] ...

最后編譯命令完成后可以看到編譯所用時間:

real 15m44.809s user 16m0.029s sys 6m22.317s

下邊是單獨使用一塊開發板進行內核編譯所耗費的時間:

real 23m33.002s user 113m2.615s sys 9m29.348s

對比可見,用采用 distcc 實現的分布式編譯可以有效提高編譯速度。

注意:

  • 平臺不同,所需的編譯器也不同。如在 x86_64 平臺上,需要安裝對應的交叉編譯工具 gcc-aarch64-linux-gnu。在 arm64 平臺則只需要安裝 gcc 編譯工具即可。用戶需要根據實際情況在對應的 Dockerfile 文件里指定安裝正確的工具。

  • 如果用 PC 機做客戶端,則在用于編譯的容器中編譯內核的時候,要用參數 CC="distcc aarch64-linux-gnu-gcc" 指明用 aarch64-linux-gnu-gcc 交叉編譯工具編譯。


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式主板
    +關注

    關注

    7

    文章

    6086

    瀏覽量

    35579
  • 安卓
    +關注

    關注

    5

    文章

    2136

    瀏覽量

    57565
  • 可制造性設計

    關注

    10

    文章

    2065

    瀏覽量

    15696
  • Firefly
    +關注

    關注

    2

    文章

    538

    瀏覽量

    7105
  • 華秋DFM
    +關注

    關注

    20

    文章

    3494

    瀏覽量

    4722
收藏 人收藏

    評論

    相關推薦

    Firefly-RK3399 Android8.1固件,可調用神經網絡API進行硬件加速

    本帖最后由 人間煙火123 于 2018-7-31 17:45 編輯 Firefly-RK3399 Android8.1 固件支持Android Neural Networks API
    發表于 07-31 17:42

    講講怎么在Firefly RK3399上安裝Android系統

    。最近入手FireFlyRK3399板子,看到了官網給的API是可以設置靜態IP的,于是嘗試了一下。真的可以!!  進入正題,講講怎么在Firefly
    發表于 10-18 16:21

    RK3399-firefly開發板原理圖

    RK3399-firefly開發板原理圖
    發表于 09-16 09:35 ?292次下載

    Firefly-RK3399--接口介紹

    Firefly-RK3399 提供了豐富的接口,主要包括:電源接口,
    的頭像 發表于 11-19 15:25 ?3933次閱讀
    <b class='flag-5'>Firefly-RK3399</b>--接口<b class='flag-5'>介紹</b>

    Firefly-RK3399--FAQs簡介

    Firefly-RK3399 的 HDMI 能自動識別顯示的分辨率。
    的頭像 發表于 11-19 15:27 ?3252次閱讀
    <b class='flag-5'>Firefly-RK3399</b>--FAQs簡介

    Firefly -RK3399電源適配器介紹

    Firefly-RK3399開發板正常工作需要電源12V/2A,電流低于2A可能會因電流過小而異常重啟,為了保證開發板的正常工作,請使用電壓為12V,電流為2A~3A的電源,推薦使用Firefly官網電源配件。
    的頭像 發表于 11-20 10:19 ?2821次閱讀
    <b class='flag-5'>Firefly</b> -<b class='flag-5'>RK3399</b>電源適配器<b class='flag-5'>介紹</b>

    Firefly-RK3399--PWM介紹

    Firefly-RK3399 開發板上有 4 路 PWM 輸出,分別為 PWM0 ~ PWM3,4路 PWM 分別使用在eDP背光、MIPI背光、VDDLOG供電、紅外IR。 本章主要描述如何配置 PWM。
    的頭像 發表于 11-22 10:08 ?5599次閱讀
    <b class='flag-5'>Firefly-RK3399</b>--PWM<b class='flag-5'>介紹</b>

    Firefly-RK3399--LED 介紹

    標準的 Linux 專門為 LED 設備定義了 LED 子系統。 在 Firefly-RK3399 開發板中的兩個 LED 均以設備的形式被定義。
    的頭像 發表于 11-22 10:13 ?3570次閱讀
    <b class='flag-5'>Firefly-RK3399</b>--LED <b class='flag-5'>介紹</b>

    Firefly-RK3399--LCD介紹

    Firefly-RK3399開發板外置了兩個LCD屏接口,一個是EDP,一個是MIPI
    的頭像 發表于 11-22 10:17 ?6471次閱讀
    <b class='flag-5'>Firefly-RK3399</b>--LCD<b class='flag-5'>介紹</b>

    Firefly-RK3399--IR程序 使用

    Firefly-RK3399 開發板上使用紅外收發傳感器 IR (在 mic 接口和喇叭接口之間)實現遙控功能,在IR接口處接上紅外接收器。本文主要描述在開發板上如何配置紅外遙控器。
    的頭像 發表于 11-22 10:24 ?2116次閱讀
    <b class='flag-5'>Firefly-RK3399</b>--IR程序 使用

    Firefly-RK3399--I2C開發板介紹

    Firefly-RK3399開發板上有 9 個片上 I2C 控制器,各個 I2C 的使用情況
    的頭像 發表于 11-22 10:43 ?2572次閱讀
    <b class='flag-5'>Firefly-RK3399</b>--I2C開發板<b class='flag-5'>介紹</b>

    Firefly-RK3399--ADC開發板介紹

    Firefly-RK3399開發板上的 AD 接口有兩種,分別為:溫度傳感器 (Temperature Sensor)、逐次逼近ADC (Successive Approximation Register)。
    的頭像 發表于 11-22 10:34 ?2231次閱讀
    <b class='flag-5'>Firefly-RK3399</b>--ADC開發板<b class='flag-5'>介紹</b>

    Firefly-RK3399開發板介紹

    Firefly-RK3399有靈活的啟動方式。一般情況下,除非硬件損壞,Firefly-RK3399開發板是不會變磚的。
    的頭像 發表于 11-23 11:30 ?3513次閱讀
    <b class='flag-5'>Firefly-RK3399</b>開發板<b class='flag-5'>介紹</b>

    什么是RK3399開發板基礎配置

    FireFly-RK3399自帶的kernel默認是沒有開啟NFS服務的。因此,想要掛載到虛擬機上,必須在開發板上安裝NFS服務。而FireFly-RK3399默認是可以直接連接無線網絡的,因此,就省去了配置PC網卡的麻煩。
    的頭像 發表于 02-17 16:10 ?1760次閱讀

    Firefly-RK3399產品規格書

    Firefly-RK3399產品規格書
    發表于 07-16 10:50 ?3次下載
    主站蜘蛛池模板: 紧致肉肉高h | 伦理 电影在线观看百度影音 | 99久久久无码国产精品免费人妻 | 日本 稀土矿| 一二三四在线高清中文版免费观看电影 | 俄罗斯大白屁股 | 精品国产90后在线观看 | 操他射他影院 | a级成人免费毛片完整版 | 国产色精品久久人妻无码 | 婷婷开心激情综合五月天 | 一二三四在线视频社区 | 啪啪后入内射日韩 | 最近韩国日本免费观看mv免费版 | 午夜免费福利小电影 | 伊人久久大香线蕉观看 | 午夜福利不卡片在线播放免费 | 91香蕉福利一区二区三区 | 国产亚洲精品久久久久小 | 伊人久久综在合线亚洲 | 午夜电影三级还珠格格 | 纲手胸被爆羞羞免费 | 最好看中文字幕国语 | 亚洲 天堂 国产在线播放 | 成人动漫百度影音 | 99国产在线视频有精品视频 | 伦理片午夜在线视频 | 一级毛片在线免费视频 | 最近的中文字幕2019国语 | 古代荡乳尤物H妓女调教 | 啦啦啦 中文 日本 韩国 免费 | 成人性生交大片免费看4 | 日本xxx在线观看免费播放 | 国产成人免费观看 | 波多野结衣的AV一区二区三区 | 久久re热在线视频精99 | 韩国污动漫无遮掩无删减电脑版 | 欧美美女论坛 | 国产精品亚洲电影久久成人影院 | 挺进绝色老师的紧窄小肉六 | 亚洲 欧美 国产 综合 播放 |