实验室准备在目前的电台基础上加上认知功能,准备试试能否引入一些机器学习的算法,因此需要调研一些相关的解决方案。目前手头有一个Google Coral的Edge TPU,是USB接口的,因此本文就从Zynq的USB入手,移植一个边缘AI方案,同时看看能不能借助于USB接口,给Zynq带来更多的拓展。
Zynq + AI
目标:给Zynq平台加上深度学习的推理加速能力。
方案
Vitis AI
Xilinx提供的DPU IP核,可以直接加入Zynq的PL部分。
支持框架:
- Caffe
- Pytorch
- Tensorflow
Pros:
- 集成度高
Cons:
- 暂时不清楚具体性能表现
- 需要Vivado 2021以上,需要迁移大量代码
- 目前最新版Vitis AI 2.0已经停止了对Zynq-7000系列的支持
Google Coral
Google提供的边缘版本的TPU。
支持接口:
- USB
- PCIe(M.2和Mini PCIe)
支持框架:
- Tensorflow Lite
Pros:
- 对TF Lite的原生支持(一般来说转模型都会有各种各样的乱七八糟的问题)
- 接口支持广(不管是物理上的还是电路上的),甚至有SoM的单独的芯片可用
Cons:
- 仅支持TF Lite
Intel NCS
Intel开发的边缘加速硬件,基于其视觉处理器 (VPU)。
开发基于Intel的OpenVINO框架。
也有单独的Chip卖。
支持接口:
- USB
支持框架:
- TF
- Caffe
- Pytorch
- mxnet
- Keras
- ONNX
Pros:
- 在调研的所有硬件中,支持最多的框架
UP AI Core X
就是上面那个的封装版,不过接口不一样
支持接口:
- PCIe(M.2和Mini PCIe)
支持框架:
同上
Pros:
- 和上面的互补
Lightspeeur
一个硅谷StartUp整的神经网络加速器,按他们的说法TOPs per Watt更优秀。
支持接口:
- USB
支持框架:
- TF
- Caffe
Jetson
老黄家的边缘加速模块。
有人做了类似的产品,比如Deepwave的AIR-T系列。
支持接口:
- SO-DIMM
- SoM
支持框架:
- CUDA
Pros:
- 因为用的是CUDA,理论来说对所有框架都有很好的支持
Cons:
- 胶水连接会造成更大的体积和功耗
移植Coral运行时
Google Coral官方没有支持Zynq,需要交叉编译。
按照官方的文档,必须要编译libedgetpu
和tflite_runtime
两个组件,如果使用的是PCIe版本的Coral还需要加上gasket-dkms
(目前暂时不加),然后根据使用的语言不同,可以加上libcoral的C++或者Python的API(可选)。
libedgetpu
Google比较特立独行,推荐用自己出的bazel进行辅助编译,Makefile接近残废,还需要一堆依赖(Google简直就是开源界的360全家桶),暂时不考虑和Buildroot的集成吧。
按照官方文档的说法,使用Bazel + Docker的方案。
建议准备好旁路路由等方案,提供一个良好的网络环境。
git clone https://github.com/google-coral/libedgetpu.git
观察Makefile
里的Docker commands有关字段,可以看见DOCKER_CPUS
支持的目标是k8 armv7a aarch64
,根据教程文档,k8
是给PC用的,而Zed对应的是armv7a
。
先编译一份PC用的:
DOCKER_CPUS="k8" DOCKER_IMAGE="ubuntu:18.04" DOCKER_TARGETS=libedgetpu make docker-build
再编译一份Zed的:
DOCKER_CPUS="armv7a aarch64" DOCKER_IMAGE="debian:stretch" DOCKER_TARGETS=libedgetpu make docker-build
参考:google-coral/libedgetpu: Source code for the userspace level runtime driver for Coral.ai devices.
tflite_runtime
官网下载的pycoral包依赖于tflite_runtime:2.5.0
,所以要切换到2.5版本,同时板子上的python是3.9,而默认build出来的是3.7,所以要把docker镜像换成bullseye的,然后按照这个issue的方法,注释Python2的包。
git checkout a4dfb8d1a71385bd6d122e4f27f86dcebb96712d -b tf2.5
cd tensorflow/lite/tools/pip_package
make BASE_IMAGE=ubuntu:18.04 PYTHON=python3 TENSORFLOW_TARGET=native docker-build
make BASE_IMAGE=debian:bullseye PYTHON=python3 TENSORFLOW_TARGET=rpi docker-build
参考:tensorflow/tensorflow/lite/tools/pip_package at master · tensorflow/tensorflow
Python 3.9 support · Issue #6 · google-coral/pycoral
Cross compilation TensorFlow Lite with CMake
Python 快速入门 | TensorFlow Lite
libcoral
应该用不到C++接口,先放这里备用。
git clone --recurse-submodules https://github.com/google-coral/libcoral
cd libcoral
make DOCKER_IMAGE=debian:buster DOCKER_CPUS="k8 armv7a aarch64" DOCKER_TARGETS=tests docker-build
参考:google-coral/libcoral: C++ API for ML inferencing and transfer-learning on Coral devices
pycoral
git clone --recurse-submodules https://github.com/google-coral/pycoral
cd pycoral
./scripts/build.sh
make wheel
不知道为什么老是build失败,目前暂时使用了官网上下载的wheel包直接安装。
结果发现,官网上下载的包实际上基于的是2.5.0.post1
版本,所以只能使用pip在线安装,因为找不到怎么本地构建这个版本的tflite_runtime:
python3 -m pip install --extra-index-url https://google-coral.github.io/py-repo/ pycoral~=2.0 --proxy=http://192.168.3.102:7890
别忘了开代理,懂得都懂。
USB无法识别
可能需要重新编译内核,按照Xilinx官方的说法,配置一下USB OTG相关的项目。
另外,也借此机会加上无线网卡和ip_table模块的驱动。
最后发现,真正的问题在于底板上需要通过跳线指定USB的工作模式,比如P9的1-2连通表示OTG模式,而板子上的跳线帽已经不见了,USB因此工作不正常。接好跳线就好了。
参考:Zynq Linux USB Device Driver – Xilinx Wiki – Confluence
菜鸟笔记–linux内核配置iptables_中华田园巨龙的博客-程序员ITS401_iptables 内核配置
iptables的内核配置
PicoZed SDR Breakout Carrier Card Hardware User Guide
测试一下
先跑官方例程,因为demo是图像识别,需要加上libjpeg。
Target packages ->
Libraries ->
Graphics ->
jpeg support = Y
[root@NJURadio /nfs/pycoral] # ./run_demo.sh
usb 1-1: reset high-speed USB device number 2 using ci_hdrc
usb 1-1: reset high-speed USB device number 2 using ci_hdrc
usb 1-1: device firmware changed
usb 1-1: USB disconnect, device number 2
usb 1-1: new high-speed USB device number 3 using ci_hdrc
----INFERENCE TIME----
Note: The first inference on Edge TPU is slow because it includes loading the model into
Edge TPU memory.
161.1ms
19.6ms
19.6ms
19.6ms
19.6ms
-------RESULTS--------
Ara macao (Scarlet Macaw): 0.75781
参考:Get started with the USB Accelerator | Coral
Run inference on the Edge TPU with Python | Coral
Zynq + 4G
HUAWEI E8372h-155适配
内核
Device Drivers ->
USB support ->
USB Modem (CDC ACM) support = Y
USB Wireless Device Management support = Y
USB Serial Converter support ->
USB driver for GSM and CDMA modems = Y
Network device support ->
USB Network Adapters ->
Multi-purpose USB Networking Framework ->
CDC EEM support = Y
CDC NCM support = Y
Huawei NCM embedded AT channel support = Y
CDC MBIM support = Y
Rootfs
Target packages ->
Hardware handling ->
usb_modeswitch = Y
usb_modeswitch_data = Y
usbutils = Y
测试
一开始使用的是mdev,在插入4G网卡后,会提示插入了一个大容量存储设备,并且出现了一个SCSI设备,这里面包含了驱动程序,但是一方面内核没有加入对USB SCSI的支持,另一方面设备没有自带ARM的驱动,需要的驱动已经在上一步编译进了内核,所以不用管,只需要把设备切换一下模式就行。
usb_modeswitch -W -v 12d1 -p 1f01 -J
-J
代表--huawei-new-mode
,也就是默认的工作模式,E8372这款产品相比一些传统的产品有一个新功能,可以模拟成一个USB的以太网设备,这样就可以无需任何干预使用预先配置的APN直接拨号,免去在开发板上拨号的麻烦,不过E8372也支持传统的modem方式工作,只需要把参数改成-X
即--huawei-alt-mode
就可以用pptd
和wvdial
等工具拨号上网。传统modem的好处在于可以通过一些现有的开源软件(比如gammu)收发SMS。
切换模式后,内核打印会提示发现新的设备:
cdc_ether 1-1:1.0 eth1: register 'cdc_ether' at usb-ci_hdrc.0-1, CDC Ethernet Device, [HWAddr REDACTED]
然后用网络工具配置一下这个网口就行:
udhcpc -i eth1
这样就可以正常使用4G网卡了。
部署
为了方便调试,所以添加了usbutils软件包,因此将mdev换成了eudev,eudev会自动完成模式的切换,只需要配置网络就行。
可以添加一条自定义的udev rules,放在/usr/lib/udev/rules.d
或者/etc/udev/rules.d
目录下,前者似乎已经有一些默认的rules,因此我放在后者里面。
创建一个文件70-huawei_e8372.rules
,写入以下内容:
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="14db", RUN+="/sbin/udhcpc -i eth1"
这样在插入网卡后,等待约30秒,就能直接上网了。
参考:Huawei E3531 on embedded device – USB_ModeSwitch
armbian_E8372h-155_4G棒 – osnosn – 博客园
Raspbian上安装使用华为E8372 | 类库大魔王的挖井日记
GSM Internet on Raspberry Pi using Huawei E8372 WiFi Dongle
usb_modeswitch移植到海思3531D平台(华为E8372h-155)_WangRayTong的博客-CSDN博客
通过wvdial完成4G自动拨号上网_lcokenm的博客-CSDN博客_wvdial
功能近乎完美的短信网关解决方案:树莓派+上网卡+MQTT – 『HomeAssistant』综合讨论区 – 『瀚思彼岸』» 智能家居技术论坛 – Powered by Discuz!
让你的树莓派和手机备号不再吃灰:短信转发_电脑整机_什么值得买
Zynq + Webcam
摄像头是罗技的C270,内核中已经包含了相应的驱动。
Buildroot里添加:
Target packages ->
Graphic libraries and applications (graphic/text) ->
fswebcam = Y
使用fswebcam –no-banner -r 640x480 test.jpg
来拍摄一张测试照片。
实际使用中也可以用ffmpeg
或者OpenCV来进行操作。
Zynq + USB Ethernet
目前市面常见的(我见过)的USB以太网卡主要有两种,一种是基于ASIX方案的,另一种则是基于Realtek方案的,目前暂时先把这两者加入内核:
Device Drivers ->
Network device support ->
USB Network Adapters ->
USB RTL8150 based ethernet device support = Y
Realtek RTL8152/RTL8153 Based USB Ethernet Adapters = Y
Multi-purpose USB Networking Framework ->
ASIX AX88xxx Based USB 2.0 Ethernet Adapters = Y
ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet = Y
更新内核,即可使用大部分市售的USB有线网卡。
Zynq + Audio
我购买了一个绿联的USB2.0声卡,通过lsusb
查询得知使用的是Unitek Y-247A方案,修改内核配置如下:
Device Drivers ->
Sound card support ->
Advanced Linux Sound Architecture = Y ->
USB Sound devices = Y ->
USB Audio/MIDI driver = Y
更新内核后,插入USB声卡,可以看见已经正常识别为了ALSA设备:
[root@NJURadio ~] # cat /proc/asound/devices
0: [ 0] : control
16: [ 0- 0]: digital audio playback
24: [ 0- 0]: digital audio capture
33: : timer
然后,在rootfs中加入alsa-utils
的aplay
和arecord
工具,并安装mpv软件,方便播放其他音频进行测试。
Target packages ->
Audio and video applications ->
alsa-utils = Y - >
aplay/arecord = Y
mpv = Y
对
alsa-utils
包内部组件的修改必须无法通过增量编译实现,必须重新编译整个包。
使用mpv播放音乐:
mpv Zeebrugge.mp3
使用ffmpeg
录制音频:
ffmpeg -f alsa -ac 1 -i hw:0,0 ffmpeg-test.wav
使用arecord
录制音频:
arecord -f cd -d 5 alsa-test.wav
目前录制的时候似乎只能使用wav格式录制,ffmpeg
如果选择mp3格式会提示没有编码器,但是配置的时候是配了全部编码器的,也许只是mp3一个格式不支持,有空的话可以测试一下其他常见音频格式。
另外,使用绿联的这款Unitek Y-247A方案USB声卡可以正常播放音频,但是在录制的时候会报错:
usb 1-1: cannot submit urb 0, error -28: not enough bandwidth
如果更换
arecord
的参数,也有可能会报其他的错,但反正就是不能工作。
因为播放是正常的,所以应该不是带宽真的不够,更换上面使用过的罗技C270摄像头作为录制设备,这个摄像头有一个单声道的麦克风,是可以正常录制的,我的猜想还是内核配置的问题。
由于最后更有可能使用一个板载的SPI或者I2C的声卡而非USB声卡工作,因此驱动很可能还需要进一步调试,在此处纠结意义不大,因此暂时不考虑这个问题。
参考:C-Media Electronics Audio Adapter (Unitek Y-247A)
[Audio]音频相关概念及参数 – 知乎
[Audio]ALSA逻辑设备篇 – 知乎
[Audio]音频相关概念及参数 – 知乎
arecord录音报错的解决办法_zkw_1998的博客-CSDN博客
Zynq + WiFi
TP-Link TL-WN823n
购买了一个TP-Link的TL-WN823N(免驱版)无线网卡,当然不对Linux免驱就是了。
按照USB接口上的喷码“220402 Ver2.0”判断,这个网卡的硬件版本应该是2.0,但是TP-Link的官网上非常乱,只能找到3.0版本的Linux驱动,TP-Link的美国官网倒是很清晰,提供了2.0的Linux驱动,同时指出了芯片是RTL8192EU,但是美版的V2和国行的V2未必相同,暂且死马当活马医。
接入USB接口,lsusb
信息如下:
Bus 001 Device 012: ID 0bda:a192 Realtek Semiconductor Corp. DISK
看来还要用usb_switchmode
切换一下,这个productID在http://www.linux-usb.org/usb.ids找不到,有理由怀疑是国内特供,有点后悔买免驱版的了,还要处理这个额外的切换问题。
有的文章提到了可以用usb_modeswitch -KW -v 0bda -p a192
切换,切换之后确实变了:
Bus 001 Device 013: ID 2357:0135 TP-Link 802.11n WLAN Adapter
但是这个productID数据库里面也没找到,而且ifconfig
也没反应,应该还是要加入一些驱动,目前使用的内核中并没有8192的驱动,螃蟹的官网也没找到,所以在GitHub上找到了一个社区维护的驱动:Mange/rtl8192eu-linux-driver: Drivers for the rtl8192eu chipset for wireless adapters (D-Link DWA-131 rev E1 included!)。
这个repo使用dkms
来管理驱动,但是在开发板上显然是不现实的,因此需要修改Makefile手动编译驱动,可以按照提供的树莓派的模板编写。
首先搜索CONFIG_PLATFORM_ARM_RPI
字段,第一处出现的应该是CONFIG_PLATFORM_ARM_RPI = n
,在其上方加入一行CONFIG_PLATFORM_ARM_ZYNQ_MINADUKI = y
,这个CONFIG_PLATFORM_ARM_ZYNQ_MINADUKI
就是要添加的自定义配置,同时找到下面的CONFIG_PLATFORM_I386_PC = y
将其改为CONFIG_PLATFORM_I386_PC = n
。
接着搜索CONFIG_PLATFORM_ARM_RPI
字段,其第二次出现应该是这一段:
ifeq ($(CONFIG_PLATFORM_ARM_RPI), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
ARCH := arm
CROSS_COMPILE :=
KVER := $(shell uname -r)
KSRC ?= /lib/modules/$(KVER)/build
MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/
endif
仿照其内容在上面加入如下段落:
ifeq ($(CONFIG_PLATFORM_ARM_ZYNQ_MINADUKI), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
ARCH := arm
CROSS_COMPILE := /tools/Xilinx/SDK/2018.3/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-
KVER :=
KSRC ?=
MODDESTDIR := $(MYMODDEST)/lib/modules/$(KVER)/kernel/drivers/net/wireless/
endif
其中KVER
和KSRC
两处留空,因为在开发中这两者可能会有变化,所以不用写死,可以在编译时指定,KVER
代表完整的内核版本,KSRC
代表内核源码的位置。MODDESTDIR
应当是安装的位置,我准备使用MYMODDEST这个环境变量来将他指定为内核make modules_install
一样的安装目录。
然后尝试编译并安装:
KVER=4.14.0-minaduki-NJURadio-20220528-gb6e379910a11-dirty KSRC=/home/minaduki/MinadukiRadio/linux-adi make -j$(nproc)
KVER=4.14.0-minaduki-NJURadio-20220528-gb6e379910a11-dirty MYMODDEST=/home/minaduki/MinadukiRadio/modules make install
结果提示没有目标目录,我打算修改Makefile手动添加一条mkdir
命令。
定位到install这个目标的地方,加入一句mkdir
命令,同时在host上执行depmod
没有意义,因此删去,加入后install应该如下所示:
install:
mkdir -p $(MODDESTDIR)
install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR)
但我转念一想,这样的话不如直接把安装的步骤放到板子上,反正总归要在板子上depmod
的。
在板子上创建一个脚本install_8192eu.sh
#! /bin/sh
KVER=$(uname -r)
MODDESTDIR=/lib/modules/${KVER}/kernel/drivers/net/wireless/
MODULE_NAME=8192eu
curr_version=$(curl --insecure https://git.nju.edu.cn/Minaduki/njuradio_binary_release/-/raw/master/thirdparty/adrv9361-z7035/tl_wn823n/latest)
mkdir -p ${MODDESTDIR}
echo ${curr_version} > ${MODDESTDIR}/VERSION
wget --no-check-certificate https://git.nju.edu.cn/Minaduki/njuradio_binary_release/-/raw/master/thirdparty/adrv9361-z7035/tl_wn823n/${curr_version}/${MODULE_NAME}.ko
install -p -m 644 ${MODULE_NAME}.ko ${MODDESTDIR}
depmod -a ${KVER}
rm ${MODULE_NAME}.ko
然后在modprobe 8192eu
的时候直接失败了,报错有一堆不知道的cfg80211的符号,应该是内核缺了一些模块导致的,重新配置内核:
Networking support ->
Wireless ->
cfg80211 - wireless configuration API = Y
Generic IEEE 802.11 Networking Stack (mac80211) = Y
结果还是不行,不过根据linux-hardware.org上查询的结果,RTL8192EU应该在4.6以后的内核中都有支持了,改为使用内核驱动:
Device drivers ->
Network device support ->
Wireless LAN ->
把常见厂家的卡和带USB的都变成M
还是不行,由于TP-Link这款网卡在数据库根本查不到,怀疑魔改过度了,说不定这个根本就不是8192eu,在网上又订了几个不同方案的网卡,明天再试。
参考:wireless – Can’t find wifi drivers for 0bda:a192 Realtek Semiconductor Corp – Ask Ubuntu
绿联AC650(产品型号CM448)
根据绿联官网上的说法,这个网卡采用的芯片是RTL8111,但是下载官方的驱动包,里面的文件夹却叫rtl8168,然后插上机器lsusb
一看,设备ID是0bda:c811
,数据库对应的RTL8821CU,那我当然不会相信官方的说法。
这款网卡虽然没有内核自带的支持,但是在GitHub上有几个社区维护的驱动,我最后选择了(star最多的)brektrou维护的版本。
编译方式与编译8192eu大同小异,也是添加一项自定义的CONFIG:
# 约100行处
CONFIG_PLATFORM_ARM_ZYNQ_MINADUKI = y
CONFIG_PLATFORM_I386_PC = n
# 约1200行处
ifeq ($(CONFIG_PLATFORM_ARM_ZYNQ_MINADUKI), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
ARCH := arm
CROSS_COMPILE := /tools/Xilinx/SDK/2018.3/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-
KVER :=
KSRC ?=
MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/
endif
然后:
KVER=4.14.0-minaduki-NJURadio-20220531-gb6e379910a11-dirty KSRC=/home/minaduki/MinadukiRadio/linux-adi make -j$(nproc)
然后就可以生成ko文件。
直接insmod
了生成的内核后,确实多出了一个wlan0
,因此在buildroot里加入和无线有关的工具:
Target packages ->
Networking applications ->
hostapd = Y
wireless tools = Y
wpa_supplicant = Y ->
Install wpa_cli binary = Y
Install wpa_passphrase binary = Y
可以用wpa_cli
工具配置网络,要使用wpa_cli
工具,需要先启动wpa_supplicant
的守护进程:
wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant.conf
然后就可以通过工具扫描附近的网络:
wpa_cli scan
wpa_cli scan_results
写一个脚本来连接网络:
#! /bin/sh
if [ $# -ne 2 ]; then
echo "Usage: ./connect_wlan.sh SSID PSK"
exit 1
else
SSID=$1
PSK=$2
fi
ifconfig wlan0 up
wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant.conf
NETWORK_ID=$(wpa_cli -i wlan0 add_network)
wpa_cli -i wlan0 set_network ${NETWORK_ID} ssid \"${SSID}\"
wpa_cli -i wlan0 set_network ${NETWORK_ID} key_mgmt WPA-PSK
wpa_cli -i wlan0 set_network ${NETWORK_ID} psk \"${PSK}\"
wpa_cli -i wlan0 select_network ${NETWORK_ID}
wpa_cli -i wlan0 enable_network ${NETWORK_ID}
udhcpc -i wlan0
成功获取到了IP地址,并且可以正常上网,可以认为绿联这款无线网卡工作正常。
最后,设计了一个脚本,使用这个脚本可以将模块自动部署到/lib/modules
目录下并depmod
,配合udev可以在USB插入后自动modprobe
,实现即插即用。
#! /bin/sh
KVER=$(uname -r)
MODDESTDIR=/lib/modules/${KVER}/kernel/drivers/net/wireless/
MODULE_NAME=8821cu
curr_version=$(curl --insecure https://git.nju.edu.cn/Minaduki/njuradio_binary_release/-/raw/master/thirdparty/rtl8821CU-gh-brektrou/latest)
mkdir -p ${MODDESTDIR}
echo ${curr_version} > ${MODDESTDIR}/VERSION
wget --no-check-certificate https://git.nju.edu.cn/Minaduki/njuradio_binary_release/-/raw/master/thirdparty/rtl8821CU-gh-brektrou/${curr_version}/${MODULE_NAME}.ko
install -p -m 644 ${MODULE_NAME}.ko ${MODDESTDIR}
depmod -a ${KVER}
rm ${MODULE_NAME}.ko
使用的eudev已经自带了这款网卡的规则,无需额外撰写命令,现在只需插上网卡,wlan0接口就会出现。
其他几款网卡还没到货,明天继续测试。
参考:buildroot如何连接wifi | Avalon
Configuring wifi in Linux with wpa_supplicant | George Ornbo
linux – Command for wpa_cli to scan a particular network SSID – Unix & Linux Stack Exchange
华硕USB-AC57和USB-AC53 Nano
按照devwiki.com的说法,这两个网卡的芯片都是RTL8812BU,所以应该可以通用,虽然内核没有支持,但是在DevWiki和linux-hardware上有数个社区维护的驱动repo,我最后选择了star最多的版本。
交叉编译过程和上面一段大同小异,不再赘述,生成的ko文件为88x2bu.ko
,使用脚本部署后,无线功能均可以正常使用。udev即插即用也工作正常。
腾达U12
腾达这款网卡根据DevWiki和linux-hardware上的情报,使用的是RTL8812AU芯片,和腾达官网上提供的Linux驱动是一致的,但可惜官网驱动仅支持到4.4版本的内核,实际编译的时候直接报错,所以还是得去找社区驱动。
腾达这官网比TP好多了,清晰不少,甚至还送了一根延长线。
最后选择了aircrack-ng维护的驱动(因为他star最多)。
交叉编译和部署均不赘述,无线功能和即插即用均能正常使用。
小结
TP-Link的网卡由于奇怪而难以理解的魔改,因此最终没能驱动起来,而剩下的网卡中,华硕AC57和腾达U12体积太大,AC53 Nano虽然很小但是已经停产,无法在正规渠道买到,对比下来绿联的AC650相对更加合适一点。
但是仍然有一个小问题,这类USB无线网卡很有可能会偷偷更换方案(点名TP-Link),需要留意这一点。
参考:Category:Linux driver/802dot11 – DeviWiki (ex WikiDevi)
en:users:drivers [Linux Wireless]
Comparison of open-source wireless drivers – Wikipedia
linux-usb.org/usb.ids
Realtek – DeviWiki (ex WikiDevi)
Zynq + webd
webd是一款超轻量的网盘软件,只有100KiB不到的体积,但是却能实现常用的上传下载功能,将webd集成进rootfs,可以简化调试时上传下载文件的过程。
Zynq对应的是armv7架构,但是实际测试的时候却发现如果使用armv7架构的可执行文件,会报错Illegal instruction
,应该是少了指令集的缘故,所以实际使用armv6架构的可执行文件。
同时,webd链接的库文件为ld-linux.so.3
,而根文件系统中提供的库文件名称为ld-linux-armhf.so.3
,需要额外做一个动态链接,否则会报一个莫名其妙的webd: no such file or directory
错误。
用
readelf
读出来的依赖库根本不是这个,而是libc和libdl,还是用qemu运行了一下才报的缺少ld-linux。
修改webd.conf
如下:
# Webd.Root: The directory that webd share on network.
# Example for Linux:
Webd.Root /
# user1 has all permissions.
Webd.User rlumS root nju
其余部分保持现状即可。
修改post_fakeroot_script.sh
,加入安装webd的命令:
#! /bin/sh
# Modify the inittab to enable serial auto-login
#sed -i 's/ttyPS0\:\:respawn\:\/sbin\/getty -L ttyPS0 0 vt100/ttyPS0\:\:respawn\:\-\/bin\/zsh/g' ${TARGET_DIR}/etc/inittab
sed -i 's/ttyPS0\:\:respawn\:\/sbin\/getty -L ttyPS0 0 vt100/ttyPS0\:\:respawn\:\-\/bin\/bash/g' ${TARGET_DIR}/etc/inittab
# Customize motd
cp /home/minaduki/buildroot_proj/mymotd ${TARGET_DIR}/etc/motd
echo "cat /etc/motd" >> ${TARGET_DIR}/etc/init.d/rcS
# Customize /etc/profile
echo "alias ll=\"ls -alF\"" >> ${TARGET_DIR}/etc/profile
# Customize bash
# \涉及到两次转译,所以要4个
sed -i "s/PS1='# '/PS1='[\\\\u@\\\\h \\\\W] \\# '/g" ${TARGET_DIR}/etc/profile
sed -i "s/PS1='$ '/PS1='[\\\\u@\\\\h \\\\W] \\$ '/g" ${TARGET_DIR}/etc/profile
echo "export HOME=/root" >> ${TARGET_DIR}/etc/profile
echo "cd \${HOME}" >> ${TARGET_DIR}/etc/profile
#echo "export PS1='[\u@\h \W] \$ '" >> ${TARGET_DIR}/etc/profile
# Customize /etc/zshrc
echo "source /etc/profile" >> ${TARGET_DIR}/etc/zshrc
echo "export HOME=/root" >> ${TARGET_DIR}/etc/zshrc
echo "export PS1='[%n@%m %~] %# '" >> ${TARGET_DIR}/etc/zshrc
echo "cd \${HOME}" >> ${TARGET_DIR}/etc/zshrc
# Add fstab entries
mkdir ${TARGET_DIR}/boot
mkdir ${TARGET_DIR}/nfs
cat /home/minaduki/buildroot_proj/fstab_patch >> ${TARGET_DIR}/etc/fstab
# Add udev rules
cp /home/minaduki/buildroot_proj/custom_udev_rules/70-huawei_e8372.rules ${TARGET_DIR}/etc/udev/rules.d/
# Install webd
cp /home/minaduki/buildroot_proj/custom_packages/webd/webd ${TARGET_DIR}/usr/bin/
cp /home/minaduki/buildroot_proj/custom_packages/webd/webd.conf ${TARGET_DIR}/etc/
cp /home/minaduki/buildroot_proj/custom_packages/webd/web/.player.htm ${TARGET_DIR}/
cp -r /home/minaduki/buildroot_proj/custom_packages/webd/web/.Trash ${TARGET_DIR}/
ln -s ${TARGET_DIR}/usr/lib/ld-2.33.so ${TARGET_DIR}/usr/lib/ld-linux.so.3
echo "/usr/bin/webd &>/dev/null &" >> ${TARGET_DIR}/etc/init.d/rcS
# Add version info
echo "Buildroot 2021.11.3 rootfs built at $(date) by ${USER}@$(hostname)" > ${TARGET_DIR}/VERSION
然后重新编译文件系统即可。