用户和密码 Ubuntu Desktop 系统 Ubuntu Desktop 系统开机启动后,自动登录到 firefly 用户。 如果有连接调试串口,串口终端自动登录 root 用户。 firefly 用户密码: firefly root 用户:默认没有设置 root 密码,firefly 用户通过 sudo passwd root 命令自行配置 root 密码。 Ubuntu Minimal 系统 Ubuntu Minimal 系统开机启动后,自动登录到 root 用户,密码为 firefly。 系统已经添加 OpenGL ES, OpenCL, DRM 支持。 Buildroot 系统 用户:root 密码:firefly ADB 使用 ADB 用Type-C data cable连接设备和主机,然后输入以下命令: adb devices adb shell 网络ADB 查看开发板 IP 地址,PC 端通过网络访问: adb connect + IP adb shell 注意点: AIO-3399-JD4 / AIO-3399J 要支持使用 ADB 需要修改 "kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-aio.dtsi",将 "usbdrd_dwc3_0"设置为"peripheral"模式,之后该usb只能作为从设备使用。 &usbdrd_dwc3_0 { dr_mode = "peripheral"; }; 同理,AIO-3399Pro-JD4 要支持使用 ADB 需要修改 "kernel/arch/arm64/boot/dts/rockchip/rk3399pro-firefly-aioc.dts"。 然后重新编译和烧写Kernel。 linux-headers 和 linux-image linux-headers 和 linux-image 是两个 deb 包,可安装在 Debian/Ubuntu 系 统中。 linux-headers 包含各种头文件,可以让设备具有本地编译驱动的能力。 linux-images 包含编译内核时产生的驱动模块,将这些模块安装到设备中,设 备才能 modprobe/insmod 进行使用。如果设备使用了 extboot,自行编译的 linux-image 内还会包含内核,安装即可直接升级内核,免去烧写步骤。 如何确定是否使用了 extboot?请前往板卡对应维基的"编译 Ubuntu 固件"页面 ,"部分编译"章节查看。如果没有 extboot 相关内容,则说明不支持。 获取方法 下载 Firefly 官方提供了两个 linux-headers 和 linux-image,方便客户在开发板 进行驱动编译。官方提供的包中不含内核,安装后不会对内核进行升级,各板型 均可使用。 各个板卡的下载请到 Firefly 官方 《资料下载》 页面下载。选择板卡后一般在“ 资源 ”处,名称为 linux-headers 。 制作 官方提供的 headers 和 image 版本和实际固件可能有差异,并且有定制需求的 客户也无法使用,因此建议通过 SDK 制作: 首先准备环境、获取 SDK、编译前配置,请前往不同板卡的维基查看,接下来在 SDK 根目录进行编译: # 选择板卡配置文件 ./build.sh xxxx.mk # 编译 ./build.sh kerneldeb 生成的文件会在 SDK 根目录: linux-headers-x.xx.xxx_x.xx.xxx-xxx_arm64.deb linux-image-x.xx.xxx_x.xx.xxx-xxx_arm64.deb 如果 SDK 使用了 extboot,那么 linux-image 包含内核,因此只能用于你在 "./build.sh xxxx.mk"所选择的型号上。 安装 以下以 ROC-RK3568-PC 安装为例: 将得到的 deb 包放入设备中,然后安装,对于 headers,安装后还需要进行编 译处理: 对于使用了 extboot 的板卡,安装后重启即可完成内核更新,之后再进行编译 headers # 安装 sudo dpkg -i linux-headers-4.19.172_4.19.172-189_arm64.deb sudo dpkg -i linux-image-4.19.172_4.19.172-189_arm64.deb # 准备编译环境 sudo apt install -y build-essential python libssl-dev # 编译 cd /usr/src/linux-headers-4.19.172 make headers_check make headers_install # make scripts 可能会出错,如果出错在 tools,可以直接忽略,安装完成 make scripts 导出设备系统 当用户已经在一台设备上完成工作环境的部署,需要将当前环境完整导出,以批 量部署到其它同设备上,可以通过导出设备文件系统来备份当前的开发环境。 导出设备系统分为两步: 在设备上导出 Ubuntu 根文件系统 rootfs; 二次打包完整固件,将 Ubuntu rootfs 与发布固件的其他分区组合,完成二次 打包,生成新的完整固件。 导出 rootfs 注意以下操作均在设备端上操作! 在设备的 Ubuntu 环境下,安装 fireflydev: sudo apt update sudo apt install fireflydev 安装 fireflydev 后,就能使用 ff_export_rootfs 脚本导出根文件系统 建议 使用容量较大的移动硬盘 导出工具会执行 apt clean 等操作以减小文件系统 大小 将根文件系统导出,例如导出到 /media/firefly/AC91-C4AE/ 目录(需 要等待一定时间): ff_export_rootfs /media/firefly/AC91-C4AE/ 压缩文 件系统,删除不必要的空白空间以减少存储器资源的占用: # 有部分客户说导 出的 rootfs 大小为 3.3G,可实际只用了 3G,原因是没有对 rootfs 进行压缩 e2fsck -p -f Firefly_Ubuntu_18.04.6_rootfs.img resize2fs -M Firefly_Ubuntu_18.04.6_rootfs.img 二次打包完整固件 注意以下操作均在 PC 机端(x86-64 架构)上操作! 安装必要的软件包:sudo apt-get install lib32stdc++6 下载二次打包工具:firefly-linux-repack(提取码:1234) 解压二次打包工具: tar -xzf firefly-linux-repack.tgz cd firefly- linux-repack 目录如下: firefly-linux-repack ├── bin │   ├── afptool │   └── rkImageMaker ├── pack.sh # 打包脚本 ├── Readme_en.md ├── Readme.md └── unpack.sh # 解包脚本 解包操作: 把官方发布的 Ubuntu 固件拷贝到 firefly-linux-repack 根目录 ,重命名为 update.img,执行解包脚本 unpack.sh。解包完成后,各分区文件 在 output 目录下。 mv /path/to/ROC- RK3566-PC_Ubuntu18.04-r21156_v1.2.4a_220519.img update.img ./unpack.sh 打包操作:保持当前目录结构,文件名等不变,接入移动硬盘到 PC 机,把前面 导出的 Ubuntu rootfs 替换 output/Image/rootfs.img,然后执行打包脚本 pack.sh。 cp /media/customer/1878-4615/Firefly_Ubuntu_18.04.6_rootfs.img /path/to /firefly-linux-repack/output/Image/rootfs.img ./pack.sh 新的完整固件为当前目录的 new_update.img。 GPIO 配置与使用 GPIO, 全称 General-Purpose Input/Output(通用输入输出),是一种软件运 行期间能够动态配置和控制的通用引脚。 以下通过控制 ROC-RK3399-PC Pro 的 LED 为例,对于其他设备,方法是类似的 。 ROC-RK3399-PC Pro 的主控是 RK3399,RK3399 有 5 组 GPIO bank: GPIO0~GPIO4,每组又以 A0~A7, B0~B7, C0~C7, D0~D7 作为编号区分。 GPIO 编号计算 ROC-RK3399-PC Pro 板载两个 LED,如下: DIY_LED 网络是接到引脚 GPIO0_B5: PIO pin 脚计算公式: pin = bank * 32 + number GPIO 小组编号计算公式: number = group * 8 + X 例如 GPIO0_B5: bank = 0; // GPIO0_B5 => 0, bank ∈ [0,4] group = 1; // GPIO0_B5 => 1, group ∈ {(A=0), (B=1), (C=2), (D=3)} X = 5; // GPIO0_B5 => 5, X ∈ [0,7] number = group * 8 + X = 1 * 8 + 5 = 13; pin = bank * 32 + number = 0 * 32 + 13 = 13; 注意:这个引脚在官方发布的固件中默认已被 LED 子系统占用,因此首先需要 找到以下节点将其 disable! ROC-RK3399-PC Pro 是定义在"arch/arm64/boot/dts/rockchip/rk3399-roc- pc.dtsi": user { status = "disabled"; // 添加这一行 label = "firefly:yellow:user"; linux,default-trigger = "ir-user-click"; default-state = "off"; gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&led_user>; }; 然后编译与重新烧写内核固件。 用户态使用 GPIO 1、申请 GPIO echo 13 > /sys/class/gpio/export 2、配置引脚方向 查看默认引脚方向: cat /sys/class/gpio/gpio13/direction 配置成输出方向: echo out > /sys/class/gpio/gpio13/direction 3、配置引脚输出电平 从前面的原理图可知,输出高电平为点亮 LED: echo 1 > /sys/class/gpio/gpio13/value 熄灭 LED: echo 0 > /sys/class/gpio/gpio13/value 设备树使用 GPIO 在设备树中配置 GPIO,需要配置引脚的功能复用与电气属性 对于 rockchip 引脚,配置如下: rockchip,pins = 其中: PIN_BANK:引脚所在的 bank PIN_BANK_IDX:引脚所在 bank 的引脚号 MUX:功能复用配置,0 表示普通 GPIO,1-N 表示特殊的功能复用 phandle:引脚一般配置,例如内部上拉、电流强度等,在 Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt文件中描 述 配置 GPIO0_B5 引脚: rockchip,pins = <0 13 RK_FUNC_GPIO &pcfg_pull_none>; 此处的含义: PIN_BANK等于0 PIN_BANK_IDX等于13 RK_FUNC_GPIO代表使用普通 GPIO 功能 pcfg_pull_none代表普通配置 对于 LED,Linux 定义了一套 GPIO 子系统,设备树的配置如下: / { gpio_led: gpio-led { compatible = "gpio-leds"; diy_led: diy-led { label = "diy-led"; default-state = "on"; // 默认打开 linux,default-trigger = "default-on"; // 默认触发 gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; // 引脚设置 pinctrl-names = "default"; pinctrl-0 = <&diy_led_pin>; // 引用 pinctrl }; }; }; &pinctrl { gpio-led-pin { diy_led_pin: diy-led-pin { rockchip,pins = <0 13 RK_FUNC_GPIO &pcfg_pull_none>; }; }; }; 然后编译与重新烧写内核固件,重启系统会看到 LED 默认点亮。 如果希望 LED 具有闪烁效果,可以修改"linux,default-trigger"属性实现: linux,default-trigger = "timer"; 配置该属性后,LED 默认每 500ms 间隔闪烁。 更多属性配置可以参考"Documentation/devicetree/bindings/leds/leds- gpio.txt"。 以上设备树配置可以在"arch/arm64/boot/dts/rockchip/firefly-gpio- demo.dtsi"找到!有需求的用户在板极设备树中包含该文件即可(记得要首先 disable "rk3399-roc-pc.dtsi"里面冲突部分): #include "firefly-gpio-demo.dtsi" 网络配置 以太网口通用参数配置 查看以太网通用参数 以太网的通用参数包括:自协商,双工模式和接口速率 ethtool eth0 配置以太网通用参数 打开或关闭自协商 ethtool -s port_name autoneg { on | off } 修改双工模式 ethtool -s port_name duplex { half | full } 注意: 当以太网接口工作在自协商模式时,缺省情况下双工模式是和对端接口协商得到 的。 当以太网接口工作在非自协商模式时,缺省情况下双工模式为全双工模式。 修改速率 ethtool -s port_name speed { 10 | 100 | 1000 } 注意: 当以太网接口工作在自协商模式时,缺省情况下接口速率是和对端接口协商得到 的。 当以太网接口工作在非自协商模式时,缺省情况下接口速率为接口支持的最大接 口速率。 配置举例 手动设置 eth0 的接口速率为 100,工作在全双工模式下。 ethtool -s eth0 autoneg off ethtool -s eth0 speed 100 ethtool -s eth0 duplex full 使用Netplan管理网络 Netplan 是一个用于在 linux 系统上轻松配置网络的实用程序。您只需创建所 需网络接口的 YAML 描述以及每个应配置的功能。根据此描述,Netplan 将为您 选择的渲染器工具生成所有必要的配置。在Ubuntu18.04及其以上版本进行了支 持。 配置 要配置 netplan,请"/etc/netplan/"使用".yaml"扩展名(例如 "/etc/netplan/config.yaml")保存配置文件,然后运行"sudo netplan apply". 此命令解析配置并将其应用于系统。 注意: 如果 netplan apply 报错,说明您的yaml配置文件未被系统支持,请仔细检查 对于以太网口,必须保证有网线接入,并且网卡灯闪烁,才能保证Netplan配置 生效 下面根据最常使用的工作场景进行配置,需要更多的配置案例教程,请阅读 netplan官方实例 基础配置 Netplan支持networkd和NetworkManager两种网络后端,一般为networkd network: version: 2 renderer: networkd 如果不存在networkd,可以使用NetworkManager,都是一样的。 network: version: 2 renderer: NetworkManager 以太网连接:动态IP network: version: 2 renderer: networkd ethernets: eth0: dhcp4: yes eth1: dhcp4: yes 以太网连接:静态IP network: version: 2 renderer: networkd ethernets: eth0: addresses: - 10.10.10.3/24 nameservers: addresses: [202.96.128.86] routes: - to: 0.0.0.0/0 via: 10.10.10.1 eth1: addresses: - 10.10.10.2/24 nameservers: addresses: [202.96.128.86] routes: - to: 0.0.0.0/0 via: 10.10.10.1 WIFI连接:静态IP network: version: 2 renderer: networkd wifis: wlan0: dhcp4: no dhcp6: no addresses: [192.168.1.200/24] nameservers: addresses: [202.96.128.86] access-points: "NETGEAR25": password: "ceshizhuanyong" routes: - to: 0.0.0.0/0 via: 192.168.1.1 WIFI连接:动态IP network: version: 2 renderer: networkd wifis: wlan0: dhcp4: yes access-points: "NETGEAR25": password: "ceshizhuanyong" 使用nmcli管理网络 nmcli是用来管理NetworkManager网络连接的命令行工具 常用命令 显示所有连接 nmcli connection show 显示连接信息 nmcli connection show connection_name 显示网络设备列表、其状态以及使用该设备的连接 nmcli device 激活连接 nmcli connection up connection_name 取消激活连接 nmcli connection down connection_name 删除连接 nmcli connection del connection_name 以太网连接:静态IP 假设进行配置以太网网卡为eth0,IP为192.168.1.10/24,默认网关为 192.168.1.1,DNS服务器为202.96.128.86 为以太网连接添加新的连接 nmcli connection add con-name Example- Connection ifname eth0 type ethernet 设置 IPv4 地址 nmcli connection modify Example-Connection ipv4.addresses 192.168.1.10/24 将 IPv4 连接方法设置为 manual nmcli connection modify Example- Connection ipv4.method manual 设置 IPv4 默认网关 nmcli connection modify Example-Connection ipv4.gateway 192.168.1.1 设置 IPv4 DNS 服务器地址 nmcli connection modify Example-Connection ipv4.dns "202.96.128.86" 激活连接 nmcli connection up Example-Connection 以太网连接:动态IP 为以太网连接添加新的连接 nmcli connection add con-name Example- Connection ifname eth0 type ethernet 激活连接 nmcli connection up Example-Connection WIFI连接:动态IP 确保 WiFi 被启用(默认) nmcli radio wifi on 刷新可用的 Wi-Fi 连接列表: nmcli device wifi rescan 查看可用的 Wi-Fi 接入点: nmcli dev wifi list IN-USE SSID MODE CHAN RATE SIGNAL BARS SECURITY ... MyCafe Infra 3 405 Mbit/s 85 ▂▄▆█ WPA1 WPA2 使用 nmcli 连接到 Wi-Fi 连接: nmcli dev wifi connect SSID-Name password wireless-password 例如: nmcli dev wifi connect MyCafe password wireless-password 请注意,如果要禁用 Wi-Fi 状态: nmcli radio wifi off 快速创建无线AP热点 对无线热点的IP局域网段无要求 在这种情况下,只需要使用nmcli命令创建一个无线AP热点即可: nmcli device wifi hotspot ifname wlan0 con-name MyHostspot ssid MyHostspotSSID password 12345678 说明: con-name:连接名称:这里设置为MyHostspot(可自定义) ssid:创建的AP热点的名称:这里设置为MyHostspotSSID(可自定义) password:创建的AP热点的密码:这里设置为12345678(可自定义) 对无线热点的IP局域网段有要求 请阅读章节《创建桥接无线AP》 创建桥接无线AP热点 功能需求 假设有一局域网,网段为"10.10.0.0",掩码为"255.255.255.0"。Firefly的开 发板,以下简称"Firefly Board",其网口通过路由器"Router",获取到本局域 网内的动态IP地址:为"10.10.0.2"。 需求:将系统配置成软路由,具体要求如下: (1)"Firefly Board"开启一个无线AP热点,平板和手机等外设通过该无线AP热 点访问网络,进行上网。 (2)"Firefly Board"开启的无线热点局域网为:"192.168.4.1" (3)"Firefly Board"如果有多个网口,要求"eth0"作为"WAN"口功能,自动从 路由器获取IP地址,"eth1"作为"LAN"口功能,能够为接入的设备分配 "192.168.4.0/24"网段的IP地址。 网络拓扑如下: 安装管理AP热点必要的软件包 安装"hostapd":"hostapd"可以用来模拟软AP,所以是实现该功能必须的: apt install hostapd 允许"hostapd"开机启动,这样重启之后无线AP热点会自动打开 systemctl unmask hostapd systemctl enable hostapd 安装"isc-dhcp-server":"isc-dhcp-server"用于为接入无线AP的设备自动分配 IP地址和DNS服务器地址 apt install isc-dhcp-server 允许"isc-dhcp-server"开启启动 systemctl enable isc-dhcp-server 安装"netfilter-persistent iptables-persistent":用于保存防火墙规则 apt install netfilter-persistent iptables-persistent 安装"bridge-utils":用于创建虚拟网桥 apt install bridge-utils 配置Netplan 目的是创建网桥"br0",网桥IP为"192.168.4.1"。允许系统"eth0"网卡分配IP地 址,禁止系统为"eth1"网卡分配IP地址,将eth1网卡绑定到网桥"br0"。 假设"netplan"的配置文件为:"/etc/netplan/netplan.yaml",内容如下所示: network: version: 2 renderer: networkd ethernets: eth0: dhcp4: yes eth1: dhcp4: no bridges: br0: dhcp4: no addresses: - 192.168.4.1/24 interfaces: - eth1 接着运行如下命令启用网络配置: netplan apply 配置hostapd 创建一个"hostapd.conf"配置文件,用来设置无线热点的名称,密码,信道等属 性 vim /etc/hostapd.conf 在其中写入如下内容: country_code=CN interface=wlan0 bridge=br0 ssid=Example-Wifi-Name hw_mode=g channel=11 macaddr_acl=0 auth_algs=1 ignore_broadcast_ssid=0 wpa=2 wpa_passphrase=12345678 wpa_key_mgmt=WPA-PSK wpa_pairwise=TKIP rsn_pairwise=CCMP 重要参数说明: country_code:国家码,中国使用CN interface:开启无线AP热点的无线网卡 bridge:绑定到br0网桥,使得无线AP热点和以太网口在同一个局域网内 hw_mode:设置无线模式 channel:信道 ssid:无线AP名称,这里设置Example-Wifi-Name wpa_passphrase:无线AP密码,这里设置为12345678 关于更多,"hostapd.conf"的配置无疑是非常复杂的,"hw_mode"支持的模式有 "a,g","channel"信道与"hw_mode","country_code"等都有关系,这里不再展 开。如果需要对这些无线参数进行更自动化且紧密的配置,可以使用"OpenWRT" 软路由系统来代替"Ubuntu"系统。 接下来,需要配置"hostapd"的全局配置文件 vim /etc/default/hostapd 取消"DAEMON_CONF"的注释,设置它的值为上面创建的"/etc/hostapd.conf" # Defaults for hostapd initscript # # See /usr/share/doc/hostapd/README.Debian for information about alternative # methods of managing hostapd. # # Uncomment and set DAEMON_CONF to the absolute path of a hostapd configuration # file and hostapd will be started during system boot. An example configuration # file can be found at /usr/share/doc/hostapd/examples/hostapd.conf.gz # DAEMON_CONF="/etc/hostapd.conf" # Additional daemon options to be appended to hostapd command:- # -d show more debug messages (-dd for even more) # -K include key data in debug messages # -t include timestamps in some debug messages # # Note that -B (daemon mode) and -P (pidfile) options are automatically # configured by the init.d script and must not be added to DAEMON_OPTS. # #DAEMON_OPTS="" 重启"hostapd"服务 systemctl restart hostapd 到此,已经可以通过手机等设备,查看到有一个无线AP热点开启,名称为 “"Example-Wifi-Name"”,但是连接之后无法为设备分配IP地址,设备会立即断 开。 配置isc-dhcp-server "isc-dhcp-server" 作为一个"dhcp"服务器,为接入无线AP节点的设备,比如拓 扑图中的"Laptop1"和"Laptop2"自动分配IP地址和DNS服务器地址。 编辑"/etc/dhcp/dhcpd.conf", vim /etc/dhcp/dhcpd.conf 用如下内容进行替换: # 为设备指定DNS地址,多个DNS使用","隔开 option domain-name-servers 202.96.128.86,202.96.128.166,8.8.8.8,114.114.114.114; default-lease-time 600; max-lease-time 7200; ddns-update-style none; ddns-updates off; subnet 192.168.4.0 netmask 255.255.255.0 { range 192.168.4.2 192.168.4.200; option routers 192.168.4.1; option broadcast-address 192.168.4.255; option subnet-mask 255.255.255.0; } 重要参数说明: domain-name-servers:DNS服务器地址列表,为接入192.168.4.0/24网段的设备 ,分配DNS subnet 192.168.4.0 netmask 255.255.255.0:定义子网网段192.168.4.0/24 range 192.168.4.2 192.168.4.200:分配的IP地址范围 option routers 192.168.4.1:默认路由 option broadcast-address 192.168.4.255:广播地址 option subnet-mask 255.255.255.0:子网掩码 重启"isc-dhcp-server",让配置生效: systemctl restart isc-dhcp-server 开启IP转发 经过如上内容的配置,接入"eth1"的设备,和连接入无线AP热点的设备,都能获 取到"192.168.4.0/24"网段的IP,且都能ping通"192.168.4.1",也可以查看到 设备获取到的"DNS"服务器地址。但是设备还无法访问internet。 开启IP转发 sysctl -w net.ipv4.ip_forward=1 设置"MASQUERADE"(地址欺骗)。"MASQUERADE"与"SNAT"作用大致一样, "MASQUERADE"不用指定明确的IP,会动态的将报文的源地址修改为指定网卡上可 用的IP地址。 iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE 注意,这里指定为"eth0",让"Firefly Board"所有的IP包全部转发到"eth0", 让外设能够进行上网,这里也可以指定为任何能访问外网的网卡,比如4G网卡 "usb0","wwan0",举一反三。 现在保存 "IPv4"(包括上面的规则)和 "IPv6" 的当前防火墙规则,以便在启 动时由 "netfilter-persistent" 服务加载: netfilter-persistent save 使用ip和netplan配置IP地址和路由 静态IP地址配置 一个网口接口上可以同时配置多个IP地址,这些IP地址可以属于同一网络,也可 以不属于同一网络。第一个配置的IP地址默认为接口的主IP地址,后面配置的IP 地址为接口的从IP地址。 常用的IP配置命令: // 设置接口的 IP 地址 ip address add PREFIX [ broadcast ADDR ] dev IFNAME // 删除接口的 IP 地址 ip address del PREFIX dev IFNAME // 查看接口的 IP 地址 ip address show/list [ dev IFNAME ] // 清空接口的所有 IP 地址 ip address flush [ dev IFNAME ] 配置举例: 为 eth0 接口配置主IP:192.168.2.2,从IP:192.168.2.3 临时配置 ip address add 192.168.2.2/24 dev eth0 ip address add 192.168.2.3/24 dev eth0 持久化配置:使用Netplan network: version: 2 renderer: networkd ethernets: eth0: dhcp4: no addresses: - 192.168.2.2/24 - 192.168.2.3/24 动态IP地址配置 操作系统一般都会为网络接口自动分配IP地址。对于 buildroot 系统中, dhcpcd服务会发送dhcp请求到DHCP服务器(这里的DHCP服务器大概率是你的路由 )请求接口的IP地址。而在Ubuntu系统中,会由NetworkManager来完成这一过程 。 临时配置 udhcpc -i eth0/eth1 # 或者 dhclient eth0/eth1 持久化配置:使用netplan network: version: 2 renderer: networkd ethernets: eth0: dhcp4: yes 静态路由配置 与静态路由相对的是动态路由,动态路由有OSPF和RIP,这两个协议只存在于路 由器中。对于非路由器设备,如果某个目的网段无法直接到达,需要配置静态路 由,告诉设备目的网段,出接口,下一跳的IP地址。 常用的配置命令: # 查看路由表 route -n # 或者 netstat -rn # 添加 IP 静态路由 ip route add PREFIX via ADDRESS dev IFNAME [ metric METRIC ] # 删除 IP 静态路由 ip route del PREFIX via ADDRESS dev IFNAME [ metric METRIC ] # 清空 IP 路由 ip route flush dev IFNAME 配置举例: 假设存在这样的一个网络拓扑,图中的Router1和Router2是我们的开发板设备, 运行的系统是Ubuntu操作系统。在这个网络中,对于Router1,网段 192.168.2.0/24和网段192.168.3.0/24,它们对于Router1属于直连网段,意味 着对于PC-A来说,访问网段192.168.2.0/24和网段192.168.3.0/24是没有问题的 ,但是却不能访问网段192.168.4.0/24。这是因为对于网段192.168.4.0/24,对 Router1来说是不可见的。需要在Router1配置静态路由,这条静态路由表明到目 的网段192.168.4.0/24,需要经过下一条IP地址为192.168.3.2/24,出接口为 Router1的eth1。同样的,对于Router2来说,网段192.168.3.0/24和网段 192.168.4.0/24属于直连网段,PC-B也同样无法访问192.168.2.0/24网段,需要 在Router2配置一条静态路由,表明到目的网络192.168.2.0/24,需要经过下一 跳IP地址为192.168.3.1/24,出接口为为Router2的eth1。 临时配置 对于Router1: # 开启IP转发功能 echo 1 > /proc/sys/net/ipv4/ip_forward # 设置eth0, eth1的IP地址 ip addr add 192.168.2.1/24 dev eth0 ip addr add 192.168.3.1/24 dev eth1 # 配置静 态路由 ip route add 192.168.4.0/24 via 192.168.3.2 dev eth1 对于 Router2: # 开启IP转发功能 echo 1 > /proc/sys/net/ipv4/ip_forward # 设置eth0, eth1的IP地址 ip addr add 192.168.4.1/24 dev eth0 ip addr add 192.168.3.2/24 dev eth1 # 配置静态路由 ip route add 192.168.2.0/24 via 192.168.3.1 dev eth1 持久化配置 对Router1和Router2,执行以下命令永久开启IP转发 sysctl -w net.ipv4.ip_forward=1 对于Router1,配置Netplan network: version: 2 renderer: networkd ethernets: eth0: addresses: - 192.168.2.1/24 eth1: addresses: - 192.168.3.1/24 routes: - to: 192.168.4.0/24 via: 192.168.3.2 对于Router2,配置Netplan network: version: 2 renderer: networkd ethernets: eth0: addresses: - 192.168.4.1/24 eth1: addresses: - 192.168.3.2/24 routes: - to: 192.168.2.0/24 via: 192.168.3.1 默认路由配置 临时配置 对于通过DCHP服务动态获取IP地址的接口,操作系统会自动为其分配 一条默认路由。对于静态IP地址配置,需要手动为其设置默认路由。 还是以上 面的例子来讲解,假设PC-A是一个Linux操作系统,我们需要进行如下配置: # 配置网卡 IP,假设其网卡为eth0 ip addr add 192.168.2.2/24 dev eth0 # 配置默认路由 ip route add 0.0.0.0/0 via 192.168.2.1 dev eth0 持久化配置:使用Netplan network: version: 2 renderer: networkd ethernets: eth0: addresses: - 192.168.2.2/24 routes: - to: 0.0.0.0/0 via: 192.168.2.1 调整默认路由顺序 在双网口的开发板中,如果两个网口的IP地址是通过DHCP自动获取的,那么操作 系统会生成两条默认路由,每个网口分别有一条默认路由,先插入网线的网口或 者先获得IP的网口,会获得更高的路由优先级。如下所示,有两条默认路由, eth0网卡的默认路由优先级高于eth1。这就意味着开发板默认通信的时候,使用 的是eth0网卡。 root@firefly:~# ip route list default via 168.168.0.1 dev eth0 proto dhcp metric 100 default via 168.168.0.1 dev eth1 proto dhcp metric 101 168.168.0.0/16 dev eth0 proto kernel scope link src 168.168.110.72 metric 100 168.168.0.0/16 dev eth1 proto kernel scope link src 168.168.110.111 metric 101 配置举例: 假设存在一种情况,Wireless Router1的网段为192.168.3.0/24,Wireless Router2的网段为192.168.2.0/24,此时对于Firefly Board来说,eth0和eth1都 是动态获取IP地址,如果eth0的默认路由的优先级比eth1的默认路由优先级高, 通信时将使用eth0的默认路由,由于eth0所在网络无外网连接,Firefly Board 就无法访问 Internet,此时可以通过修改默认路由的优先级来解决。 其Netplan配置如下,eth1的metric数值小于eth0,数值越小优先级越高 network: version: 2 ethernets: eth0: dhcp4: yes dhcp4-overrides: route-metric: 200 eth1: dhcp4: yes dhcp4-overrides: route-metric: 100 iptables NAT配置 网络转换技术也称为NAT(Network Address Translation)技术,它的基本作用 就是实现私有IP地址和公有IP地址之间的转换。 在Linux系统中,NAT可以细化为SNAT(Source Network Address Translation) 和DNAT(Destinationnetwork address translation)。SNAT也称为源地址转换 技术,用于当私网主机向外网主机发起网络通信时,IP数据包在到达外网网络之 前,将IP数据包中的源IP修改为路由器或者防火墙的IP地址,这样外网主机就无 法获知内网主机的私网IP地址。DNAT也称为目标地址转换技术,用于当外网主机 需要访问内网主机提供的网络服务时,比如http,IP数据包到达路由器或者防火 墙时,由它们将IP数据包中的目标IP改为提供网络服务的私网主机IP。 常用命令 我们可以通过配置iptables的nat表,来实现SNAT和DNAT # 查看nat规则 iptables -t nat -vnL # 清空nat规则 iptables -t nat -F # 添加一个SNAT规则,将内网的IP,映射到外网的IP iptables -t nat -A POSTROUTING -s LocalIP -j SNAT --to-source ExtIP # 添加一个DNAT规则,将外网的IP和端口,映射到内网的IP和端口 iptables -t nat -A PREROUTING -d ExtIP -p tcp|udp --dport PORT -j DNAT --to-destination LocalIP[:PORT] iptables也支持MASQUERADE(地址欺骗),它的作用与SNAT基本相同,也可以起 到源地址转换的作用。在一种特殊情况中,如果外网的IP地址不是一个固定且长 期有效的IP地址,比如是通过pppoe进行拨号动态获取的IP地址,就可以使用 MASQUERADE来实现源地址转换。MASQUERADE则不用指定明确的IP,会动态的将报 文的源地址修改为指定网卡上可用的IP地址。 # 添加一个MASQUERADE规则,将内网的IP,映射到外网网卡所在的IP(这里的内网IP可以省略,则默认将所有内网的IP,都映射到外网网卡所在的IP) iptables -t nat -A POSTROUTING [-s LocalIP] -o IFNAME -j MASQUERADE 配置举例 假设存在这样的一个网络拓扑,用10.1.0.0/16来模拟一个公网网络,用 192.168.1.0/24来模拟私有网络。图中的机器都是用Linux主机进行模拟的机器 。 对于Router1,是一个连接内外网的路由器,其netplan配置如下: network: version: 2 renderer: networkd ethernets: eth0: addresses: - 192.168.1.3/24 eth1: addresses: - 10.1.0.7/16 同时对于Router1,需要开启IP转发功能: echo 1 > /proc/sys/net/ipv4/ip_forward 对于Internet PC,是一个外网的个人主机,其netplan配置如下: network: version: 2 renderer: networkd ethernets: eth0: addresses: - 10.1.0.6/16 对于Web Server,是一个私网服务器,提供http服务,其netplan配置如下: network: version: 2 renderer: networkd ethernets: eth0: addresses: - 192.168.1.100/24 routes: - to: 0.0.0.0/0 via: 192.168.1.3/24 SNAT 需求:目前的网络结构中,内网主机是无法访问外网的。 添加一条SNAT规则,修改内网主机发往外网的IP数据包,将源IP地址为 192.168.1.0/24网段的IP,修改为10.1.0.7 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 10.1.0.7 验证方法: 在内网的Web Server,ping外网的Internet PC ~ ping -c 4 10.1.0.6 ok PING 10.1.0.6 (10.1.0.6) 56(84) bytes of data. 64 bytes from 10.1.0.6: icmp_seq=1 ttl=63 time=2.15 ms 64 bytes from 10.1.0.6: icmp_seq=2 ttl=63 time=2.12 ms 64 bytes from 10.1.0.6: icmp_seq=3 ttl=63 time=1.99 ms 64 bytes from 10.1.0.6: icmp_seq=4 ttl=63 time=2.14 ms --- 10.1.0.6 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 7ms rtt min/avg/max/mdev = 1.989/2.098/2.147/0.063 ms 在内网的Web Server,抓包 root@firefly:/# tcpdump -i eth1 -nn icmp tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes 03:33:37.503348 IP 10.1.0.7 > 10.1.0.6: ICMP echo request, id 53287, seq 1, length 64 03:33:37.503603 IP 10.1.0.6 > 10.1.0.7: ICMP echo reply, id 53287, seq 1, length 64 03:33:38.503348 IP 10.1.0.7 > 10.1.0.6: ICMP echo request, id 53287, seq 2, length 64 03:33:38.503560 IP 10.1.0.6 > 10.1.0.7: ICMP echo reply, id 53287, seq 2, length 64 03:33:39.504601 IP 10.1.0.7 > 10.1.0.6: ICMP echo request, id 53287, seq 3, length 64 03:33:39.504812 IP 10.1.0.6 > 10.1.0.7: ICMP echo reply, id 53287, seq 3, length 64 03:33:40.505347 IP 10.1.0.7 > 10.1.0.6: ICMP echo request, id 53287, seq 4, length 64 03:33:40.505557 IP 10.1.0.6 > 10.1.0.7: ICMP echo reply, id 53287, seq 4, length 64 DNAT 需求:内网Web Server提供http服务,外网主机想要访问内网的web网页。 添加一条DNAT规则,修改外网发往内网的IP数据包,将目的IP地址,和端口号, 修改为内网Web服务器的IP和端口号。 iptables -t nat -A PREROUTING -d 10.1.0.7 -p tcp --dport 8000 -j DNAT --to-destination 192.168.1.100:8000 验证方法: 在外网Internet PC访问内网Web Server的Web服务 root@firefly:/# wget http://10.1.0.7:8000/index.html --2021-02-19 03:31:12-- http://10.1.0.7:8000/index.html Connecting to 10.1.0.7:8000... connected. HTTP request sent, awaiting response... 200 OK Length: 41323 (40K) [text/html] Saving to: ‘index.html’ index.html 100%[===================>] 40.35K --.-KB/s in 0.001s 2021-02-19 03:31:12 (29.8 MB/s) - ‘index.html’ saved [41323/41323] MASQUERADE 需求:如果连接内外网的Router1,它的外网网卡只有一个,为eth1,且IP地址 动态获取。 解决方法:添加一条MASQUERADE规则,将内网192.168.1.0/24发往外网的IP数据 包,修改其源IP地址为eth1网卡的IP地址。 iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 -j MASQUERADE iptables filter配置 iptables的filter表(过滤规则表),用于控制数据包是否允许进出及转发。 filter 表可以控制的链路有 INPUT、FORWARD 和 OUTPUT。常用的动作有ACCEPT ,DROP,REJECT。 通用命令 # 清空filter表 iptables -t filter -F # 显示filter表 iptables -t filter -nvL ACCEPT:允许数据包通过 配置举例:默认情况下ssh使用22端口进行tcp通信,如果要开启远程访问,需要 开启22端口的tcp连接。 iptables -A INPUT -t filter -p tcp --dport 22 -j ACCEPT 开启ssh访问,允许192.168.0.0/24网段进行访问 iptables -A INPUT -t filter -p tcp -s 192.168.0.0/24 --dport 22 -j ACCEPT 开启ssh访问,允许收到的数据包来源于eth0网卡 iptables -A INPUT -t filter -p tcp -i eth0 --dport 22 -j ACCEPT 开启ssh访问,允许192.168.0.0/24网段中MAC地址为00:50:8D:FD:E6:32的主机 进行访问 iptables -A INPUT -t filter -p tcp -s 192.168.0.0/24 --dport 22 -m mac --mac-source 00:50:8D:FD:E6:32 -j ACCEPT REJECT:拒绝数据包通过 REJECT动作的常用选项为–reject-with(使用–reject-with选项,可以设置提示 信息,当对方被拒绝时,会提示对方为什么被拒绝) 对于ICMP协议,可用值如下,如果不提供,默认为icmp-port-unreachable icmp-net-unreachable icmp-host-unreachable icmp-port-unreachable, icmp-proto-unreachable icmp-net-prohibited icmp-host-pro-hibited icmp-admin-prohibited 配置举例:拒接外部ping,并提示"Destination Host Unreachable" iptables -A INPUT -t filter -p icmp -j REJECT --reject-with icmp-host-unreachable DROP:丢弃数据包 配置举例:直接将外部ping包丢弃 iptables -A INPUT -t filter -p icmp -j DROP Qt 支持 Qt 环境支持 Firefly 设备系统如果是 Ubuntu 22.04 可以直接通过 apt 安装 Qt 环境: # 安装基础环境 apt update apt install -y qtcreator qtbase5-dev # 安装额外组件与开发环境,例如 apt install -y libqt5multimedia5 qtmultimedia5-dev libqt5quick5 qtdeclarative5-dev 安装后直接在设备上进行开发。 Ubuntu 18.04 或者 Ubuntu 20.04 需要借助电脑进行交叉编译,详情请看下一 章 Qt 交叉编译环境支持 Firefly 发布了两个 Qt 交叉编译工具链,适用于以下环境,请根据需求选择: Qt: 5.12.2 Host: x86-64 / Ubuntu 18.04 Target: Firefly RK3568 RK3566 RK3399 RK3328 PX30 / Ubuntu 18.04 Minimal&Desktop 和 Qt: 5.15 Host: x86-64 / Ubuntu 20.04 Target: Firefly RK3588 RK3568 RK3566 / Ubuntu 20.04 Desktop 工具链完整支持 wenEngine, 支持 EGLFS LinuxFB XCB 等 backend。 下载地址 点击 下载链接 (提取码:FFQT) 部署 详情参见工具链中的 Qt5.1x.x_Release.md 文件 注意,文档中所有路径的名称不可更改,否则会导致编译或者运行出错。 编译 在host端,进入 Qt 工程目录,"qmake && make" 即可. 运行 工具链中含有例程,用户在部署完成后,可以在 host 端 build demo,在 tartget 端运行 demo 以测试部署是否成功。 确定了使用哪个后端,就可以修改设备中 /etc/profile.d/target_qtEnv.sh 文 件,去除对应平台环境变量前面的"#"使其一直生效 # 例如,使用 XCB ,则将文件内 XCB 部分前面的 # 删除 #XCB export QT_QPA_PLATFORM=XCB export QT_QPA_EGLFS_INTEGRATION=XCB_EGL Qt 双屏异显 Firefly Ubuntu 系统可以使用 Qt 应用实现双屏显示和操作。 (1)进入桌面环境 export XAUTHORITY=/home/firefly/.Xauthority export DISPLAY=:0 (2)设置环境变量 export QT_QPA_PLATFORM=xcb export QT_QPA_EGLFS_INTEGRATION=XCB_EGL (3)运行 Demo ./firefly_arm64_qt5.12.2_18.04/demo/double_panel_demo (4)Demo 代码目录 firefly_arm64_qt5.12.2_18.04/example/double_panel_demo (5)代码编译 cd example qmake make (6)添加自己的 Qt 工程 在 example 目录下添加用户自己的 Qt 项目工程。 编辑 example 目录下 gui.pro 文件。 假设工程目录名为 double_panel_demo,则在 gui.pro 文件中追加 SUBDIRS += double_panel_demo。 执行命令qmake && make。 (7)运行效果 Qt Creator 目标平台的系统是 Ubuntu 22.04 则不用看本章节,直接在设备上使用 qtcreator,无需特殊设置。 其他版本系统需要交叉编译 qt,请继续往下看: 下面介绍主机上 Qt Creator 的使用说明, 在操作前,请先安装、配置好 Qt 交叉编译环境和运行环境 。 安装 进入 Qt 官方下载页面 ,选择一个版本下载 qt-creator-opensource-linux-x86_64-x.x.x.run,下载 完成之后,在终端执行"./xxxx.run"运行安装,注意文件需要有执行权限。 配置 下面以 firefly-qt-5.12.2-aarch64 环境作为例子进行配置,目标平台是 Buildroot 系统: 目标平台系统不同,配置也稍有不同,所以请仔细查看文字说明,图片仅供参考 ,不要照搬图片中的配置 安装完成后,启动 Qt Creator,打开菜单 "Tools -> Options",找到 Kits。 配置 Qt Versions 点击右侧 add 按钮添加,选择 Qt 环境安装位置中的 qmake 即可 qmake:/opt/firefly-qt-5.12.2-aarch64/host/bin/qmake 配置 Compilers 点击右侧 add 按钮添加 gcc 和 g++ 交叉编译器的位置 如 果主机安装了 crossbuild-essential-arm64,则编译器就在 /usr/bin/ 下 如 果使用了第三方的交叉编译器,找到安装位置并添加即可 如果目标平台是 Buildroot,则需要使用 Buildroot Qt 环境包中的编译器 g++:/opt /firefly-qt-5.12.2-aarch64/host/bin/aarch64-buildroot-linux-gnu-g++ gcc:/opt/firefly-qt-5.12.2-aarch64/host/bin/aarch64-buildroot-linux- gnu-gcc 为方便调试,配置 Debuggers 和 Devices 用于在线调试: 配置 Debuggers 首先主机中安装 gdb-multiarch:apt install -y gdb- multiarch 检查目标机上是否存在 /usr/bin/gdbserver,没有的话需要安装: apt install -y gdbserver (Buildroot 自带,无需安装) 回到主机的 Qt Creator,点击右侧 add 按钮添加 gdb 选择主机中的 gdb-multiarch : /usr/bin/gdb-multiarch 配置 Devices 设置好设备的 IP、用户名 (root) 和密码 (firefly) 。为了方 便调试,可以在设备上设置静态 IP。 GDB server 设置为 /usr/bin/gdbserver 配置 Kits 将前面设置的配置项添加到 Kits。 如果目标平台是 Ubuntu 系统 ,这一步也需要添加 sysroot 的路径 编译运行 打开 demo 程序,"Welcome -> Open Project",选择要使用的 Kits: 之后打开 "Projects -> Run",配置命令行参数,这里设置为 "-platform wayland": 目标平台是 Ubuntu 则使用 "-platform xcb" (Ubuntu 桌面环境),或者根据需 要选择 "linuxfb"、"eglfs" 配置环境变量,即 "export XDG_RUNTIME_DIR=/tmp/.xdg": RK356X Buildroot 则需要使用 "/var/run" 而不是 "/tmp/.xdg" 目标平台是 Ubuntu 则需要根据之前设置的 "platform" 添加不同的环境变量, 详情在 Qt 环境包中的说明文件中 如果目标平台的运行环境(本文开头提到的)之前已经配置好并成功运行 demo, 此时可以直接点击右侧"Fetch Device Environment" 获取目标的环境变量 编译运行: 点击 "Build" 交叉编译 Qt 程序;点击 "Run" 或 "Debug" 在设备上运行或调 试程序。要重新运行程序时,记得手动点击 "Stop" 关闭已经运行的程序。 编译生成目录和 demo 目录在同一位置。 Docker 支持 Firefly 发布的普通固件一般不满足 Docker 的运行要求,如果有需求,可以使 用 SDK 打开内核的相关配置,重新编译烧录内核以支持 Docker。 (RK356X v1.2.4a 及以后版本 、RK3399/RK3588 默认支持 Docker,可直跳到 安装 Docker 步骤) 以下案例是基于 Firefly Ubuntu 20.04,内核配置部分是通用的! 检查 Kernel 配置 首先需要通过工具检查当前设备的内核缺少了哪些 Docker 需要的配置。检测脚 本"check-config.sh"可以前往 社区论坛 获取。 获取到脚本之后,开始进行检测: #将脚本拷贝到SDK的kernel目录下 cp check-config.sh PathToSDK/kernel/ cd PathToSDK/kernel chmod +x check-config.sh #获取当前内核配置 make ARCH=arm64 firefly_linux_defconfig #检测 ./check-config.sh .config 执行后的结果如下,主要是两部分: Generally Necessary: - cgroup hierarchy: properly mounted [/sys/fs/cgroup] - apparmor: enabled and tools installed - CONFIG_NAMESPACES: enabled - CONFIG_NET_NS: enabled - CONFIG_PID_NS: enabled - CONFIG_IPC_NS: enabled - CONFIG_UTS_NS: enabled - CONFIG_CGROUPS: enabled ...... Optional Features: - CONFIG_USER_NS: enabled - CONFIG_SECCOMP: enabled - CONFIG_SECCOMP_FILTER: enabled - CONFIG_CGROUP_PIDS: enabled - CONFIG_MEMCG_SWAP: enabled ...... Generally Necessary: 表示必要的配置,如果有显示 missing 的地方,就需要 在内核配置中打开它。 Optional Features: 是可选配置,根据需要打开。 开启需要的配置 从上面的检测结果中得知需要打开哪些配置后,即可使用"make ARCH=arm64 menuconfig"进入菜单,搜索对应项目将其打开。请认真查看菜单中的操作说明 ,遇到不可选中的项目请注意依赖关系。 开启所有必要配置以及部分可选配置后,注意保存: make ARCH=arm64 savedefconfig mv defconfig arch/arm64/configs/firefly_linux_defconfig 之后进行编译内核: #退回到SDK目录 cd .. #编译内核 ./build.sh kernel 安装 Docker 烧录完新内核之后,可以开始在设备上安装 Docker (此安装方法同样适用于 PC): 步骤1:快速安装 # 这里仅介绍直接使用脚本快速安装 apt-get update wget -qO- https://get.docker.com/ | sh 等待安装成功之后应该会看见 Docker 版本信息 步骤2:检查 docker 存储位置(该步骤仅适用于 PC 安装 docker) 如果你在 Firefly 设备中安装 docker,请跳过步骤2 # 执行 docker info | grep -i dir # 执行结果 Docker Root Dir: /var/lib/docker 返回的信息显示了 docker 的默认存储位置,该位置在不同电脑上可能不一样 镜像和容器会占用大量空间,因此, 如果默认的位置空间不大,需要修改到空间充足的位置 再次强调,此步骤只用于 PC,Firefly 设备中,修改此位置会导致 docker 无 法工作 ,请直接跳到下一步 # 先关闭 docker 服务 sudo systemctl stop docker # 修改文件 /lib/systemd/system/docker.service sudo vim /lib/systemd/system/docker.service # 在这一行末尾添加想要修改的位置 --graph /home/firefly/docker/data ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --graph /home/firefly/docker/data # 重启 docker 服务 sudo systemctl daemon-reload sudo systemctl start docker # 检查位置是否修改成功 docker info | grep -i dir Docker Root Dir: /home/firefly/docker/data 步骤3:将自己的用户添加到 docker 组 sudo usermod -a -G docker firefly # 添加后重启 sudo reboot 步骤4:重启后运行 demo 测试是否正常: firefly@firefly:~# docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 93288797bd35: Pull complete Digest: sha256:cc15c5b292d8525effc0f89cb299f1804f3a725c8d05e158653a563f15e4f685 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (arm64v8) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/ ROS 支持 安装 ROS 首先按照官方安装教程安装,根据系统选择对应ROS版本安装。 官方安装教程 安装 GLX 库 rviz,gazebo是基于GLX编写的,我们系统目前只支持EGL,所以他们无法使用GPU 加速,同时需要安装GLX库才能能够正常运行。 apt install -y libgl1-mesa-glx libgl1-mesa-dri libglx-mesa0 reboot 更新 libqt5opengl5-dev 如果遇到rviz还不能运行,rqt报QOpenGLTimeMonitor等错误,需要更新官方的 libqt5opengl5-dev, 执行下面操作,再尝试运行rqt、rviz和gazebo等程序 sed -i 's/.*wiki.t-firefly.com.*/\#&/' /etc/apt/sources.list apt install libqt5opengl5-dev sed -i '/.*wiki.t-firefly.com.*/s/^#//' /etc/apt/sources.list wayland 下运行 rviz,rqt 和 gazebo 等程序 XWayland说明 基于GLX的程序在wayland运行,需要使用XWayland。使用 QT_QPA_PLATFORM=xcb 强制Qt应用程序使用X11 QT_QPA_PLATFORM=xcb rviz QT_QPA_PLATFORM=xcb rqt QT_QPA_PLATFORM=xcb gazebo # 也可以将该环境设置到.bashrc,就可以直接运行rviz等程序。 echo "export QT_QPA_PLATFORM=xcb" >> /~/.bashrc ROS教程 显示架构支持 对于 Rockchip 平台,主要有以下几种显示架构可供选择: Qt + Wayland Qt + EGLFS EGL program + X11 Wayland None 多窗口的功能需求,选择: X11 Wayland 桌面的功能需求,选择: X11 4K 视频播放 + 全屏: Qt + Wayland Qt + EGLFS X11 Wayland 4K 视频播放 + 多窗口: X11 Qt + Wayland Wayland 如果您对显示架构的技术不太理解,可以继续往下阅读。 X11 X11 是 X 显示协议的第 11 个版本。 X 协议已经延用了 30 年,X 协议的 Client/Server 结构起初是为了在以前硬件性能太弱的情况下,设备(Client 端)通过发送渲染请求给 X server(以前 X server 是运行在另一个独立的硬 件)渲染显示。 但是随着现代硬件性能不断提升,同一个硬件系统上可以同时 运行 Client 和 Server 了,但是这种远程通讯结构运用在本地机器上带来的后 果就是性能的丢失,目前在 Debian 官方已经有分支在开发 Wayland 用于替换 掉 X11,但是目前 Wayland 对现有软件兼容性并不好所有还没有正式替换使用 。 参考资料: https://en.wikipedia.org/wiki/X.Org_Server https://www.comptechdoc.org/os/linux/howlinuxworks/linux_hlxwindows.html https://dri.freedesktop.org/wiki/DDX/ https://www.freedesktop.org/wiki/Software/Glamor/ https://en.wikipedia.org/wiki/X.Org_Server Qt + EGLFS Qt + EGLFS 是 Qt 自己实现的一个 GUI 系统,不支持多窗口,但也因此少了 window composite。 Qt + EGLFS 和 dri2 的方式类似,区别就在于 Qt + EGLFS 的 font buffer 在自己用 gpu composite 后,是直接送给 DRM 显示,而 X 里是 送至 Window manager 做 composite,所以 EGLFS 在效率上是有优势的。 Qt + Wayland 在 Wayland 中, Weston 是 Wayland 显示协议中的具体实现,其对应关系就好比 Xorg (X server)和 X 的关系一样。 目前 Wayland 和 X 对比唯一缺点就是在兼容性上了,所以目 前主流的系统版本中依然大部分使用 X。 Weston 不再使用 X 的 Client/Server 的结构,而是直接由合成器接受内核事件,并传递给 Client 端 ,由 Client 端直接渲染,只向合成器发送需要更新的区域,再由合成器通知内 核安排翻页。 需要注意的是由于 Ubuntu/Debian 已经有 X11,所以 SDK 默认 是在 Buildroot 添加了 Weston 的支持,实际上如果 Ubuntu/Debian 需要安装 Weston 的话也可以在 Minimal 版本上搭建。(Firefly Ubuntu 20.04,将会默 认自带 Wayland 和 X,并且可以自由切换。) 建议使用 Buildroot/Yocto 做 Wayland 的开发。效率上 Wayland 要比 X11 好 点,主要是兼容性问题。如果不需要桌面,又要多窗口,可以尝试使用 Wayland 。 None 除了 X11 和 Wayland 之外,还有 None ,这也是嵌入式上接触比较多的。比如 MiniGUI,SDL皆是如此。 若要支持到 DRM 和 opengl 的话,就只能选择 Qt 了。 MiniGUI 是一个定位于轻量级的嵌入式图形库,对系统资源的需求完全考虑到了嵌入式 设备的硬件情况,如 MiniGUI 库所占的空间最小可以裁剪到 500K 左右。 针对 Buildroot 系统适配在硬件资源比较紧张的设备上的特性,MiniGUI 搭配 Buildroot 是再适合不过了。 参考资料: https://wayland.freedesktop.org/architecture.html https://en.wikipedia.org/wiki/Wayland