Site Overlay

Zynq + More

实验室准备在目前的电台基础上加上认知功能,准备试试能否引入一些机器学习的算法,因此需要调研一些相关的解决方案。目前手头有一个Google Coral的Edge TPU,是USB接口的,因此本文就从Zynq的USB入手,移植一个边缘AI方案,同时看看能不能借助于USB接口,给Zynq带来更多的拓展。

Zynq + AI

目标:给Zynq平台加上深度学习的推理加速能力。

方案

参考:AI边缘计算(嵌入式AI)硬件信息汇总_myg22的博客-CSDN博客

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,需要交叉编译。
按照官方的文档,必须要编译libedgetputflite_runtime两个组件,如果使用的是PCIe版本的Coral还需要加上gasket-dkms(目前暂时不加),然后根据使用的语言不同,可以加上libcoral的C++或者Python的API(可选)。

参考:Build Coral for your platform | Coral

libedgetpu

Google比较特立独行,推荐用自己出的bazel进行辅助编译,Makefile接近残废,还需要一堆依赖(Google简直就是开源界的360全家桶),暂时不考虑和Buildroot的集成吧。

按照官方文档的说法,使用Bazel + Docker的方案。

我就很想吐槽Google的自信,我承认Docker可以很好解决依赖带来的问题,但是你完全可以弄一个准备好的镜像,而不是一个裸镜像 + 脚本,这样完全没法用到已经配置好的镜像和代理,你猜我连不连得上GitHub?

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

别忘了开代理,懂得都懂。

参考:Software | Coral

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
[[email protected] /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就可以用pptdwvdial等工具拨号上网。传统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来进行操作。

参考:树莓派中测试USB摄像头_大力挥拳的博客-CSDN博客

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设备:

[[email protected] ~] # cat /proc/asound/devices
  0: [ 0]   : control
 16: [ 0- 0]: digital audio playback
 24: [ 0- 0]: digital audio capture
 33:        : timer

然后,在rootfs中加入alsa-utilsaplayarecord工具,并安装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

其中KVERKSRC两处留空,因为在开发中这两者可能会有变化,所以不用写死,可以在编译时指定,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='[\\\\[email protected]\\\\h \\\\W] \\# '/g" ${TARGET_DIR}/etc/profile
sed -i "s/PS1='$ '/PS1='[\\\\[email protected]\\\\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='[\[email protected]\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='[%[email protected]%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

然后重新编译文件系统即可。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据