2024-03-27
在本地没有联网的数字中继或本地数字中继较远的情况下, MMDVM 盒子是数字电台全球通联的常用设备。
MMDVM 盒子通常使用树莓派作为上位机,控制 MMDVM 单/双工热点板。相对 MMDVM 热点板来说,树莓派更为昂贵,故尝试使用便宜得多的 Milkv Duo 替代树莓派。
在上次的文章中, Milkv Duo 配合 MMDVMHost 成功实现了对 MMDVM 单/双工热点板的控制,但是依然遗留了一些问题:
- 没有屏幕显示
- 官方镜像 RAM 空闲过少
- 无法通过 Wifi 连接
而这次采用了 1602 液晶作显示, RTL8188 系列无线网卡实现 Wifi 联网。
MMDVMHost 的液晶驱动需要适配,本文只给出适配完成后的仓库;另外疑似会有开源协议冲突,并不提供担保。
本文只给出部署的过程,工具链同样使用了 RUYI 包管理器安装的工具链,具体安装方法参考上次的文章。
构建 wiringX
wiringX 用于驱动 GPIO。 Milkv Duo 的 wiringX 支持在最近被合入主线,而主线分支和 Milkv Duo 的文档会有些许不同,故 wiringX 需要使用最新主线。 DESTDIR
变量请按实际情况修改。
$ git clone --depth=1 https://github.com/wiringx/wiringX.git
$ cd wiringX
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_C_COMPILER=riscv64-plct-linux-gnu-gcc
$ make -j4
$ make install DESTDIR=<ruyi_venv_dir>/venv-duo/wiringx
构建 MMDVMHost
本身 MMDVMHost 被设计为运行在树莓派上,故其使用 wiringPi 作为 GPIO 驱动。为了使其能够在 Milkv Duo 上驱动 1602 液晶,这里做了 wiringX 的适配,并开源在如下所示的仓库里。
在适配过程中,一些 wiringPi 的库被稍加修改拿来用了,故疑似有源码协议冲突的问题,暂时不知道如何解决。
$ git clone https://github.com/weilinfox/MMDVMHost_Duo.git -b duo
$ cd MMDVMHost_Duo
修改 Makefile,工具链名称以及依赖库所在的位置要根据实际情况修改,这里扔一个 patch 作为描述。
--- Makefile.Duo.HD44780 2024-03-24 23:38:17.995092253 +0800
+++ Makefile.Duo.HD44780.use 2024-03-20 23:18:25.395561053 +0800
@@ -1,9 +1,9 @@
# This makefile is for use with the Raspberry Pi when using an HD44780 compatible display. The wiringpi library is needed.
-CC = riscv64-unknown-linux-musl-gcc
-CXX = riscv64-unknown-linux-musl-g++
-CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DHD44780 -I/usr/local/include/
-LIBS = -lwiringx -lpthread -lutil -lsamplerate -L/usr/local/lib/
+CC = riscv64-plct-linux-gnu-gcc
+CXX = riscv64-plct-linux-gnu-g++
+CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DHD44780 -I/home/hachi/Documents/Working/ruyi-venv/venv-duo/libsamplerate/usr/local/include/ -I/home/hachi/Documents/Working/ruyi-venv/venv-duo/wiringx/usr/local/include/
+LIBS = -lwiringx -lpthread -lutil -lsamplerate -L/home/hachi/Documents/Working/ruyi-venv/venv-duo/libsamplerate/usr/local/lib/ -L/home/hachi/Documents/Working/ruyi-venv/venv-duo/wiringx/usr/local/lib/
LDFLAGS = -g -static
OBJECTS = \
构建。
make -f Makefile.Duo.HD44780 -j4
安装 1602 液晶
由于不想使用 duo-pinmux
命令手动修改引脚功能,这里选了默认设为 GPIO 功能的引脚用于连接 1602 液晶。实测 5V 液晶可以被正常驱动。
首先给出 MMDVM.ini 中与 1602 相关的配置。
[General]
Display=HD44780
[HD44780]
Rows=2
Columns=16
# rs, strb, d0, d1, d2, d3
Pins=16,17,18,19,20,21
硬件连接如下表所示。
Milkv Duo | 1602 |
---|---|
GND | VSS |
VBUS | VDD |
- | VO |
GP16 | RS |
GND | RW |
GP17 | E |
- | D0 |
- | D1 |
- | D2 |
- | D3 |
GP18 | D4 |
GP19 | D5 |
GP20 | D6 |
GP21 | D7 |
VBUS | A |
GND | K |
其中 VO 为显示偏压,可以串一电位器到 GND 用于调整;另外由于 MMDVMHost 采用了 4 线连接的方案, D0-D3 悬空。
MMDVMHost 还提供了基于 PWM 的动态背光。尽管 wiringX 似乎并没有 PWM 支持, MMDVMHost 还提供了基于软件的 PWM 背光控制。不过这些都需要附属电路来实现,有需要的可以自行解决。
构建新的 Milkv Duo 镜像
重构镜像的目的在于增加可用 RAM 以及带 RTL8188 无线网卡驱动的内核。
首先克隆最新的主线分支。
$ git clone https://github.com/milkv-duo/duo-buildroot-sdk.git
$ cd duo-buildroot-sdk
注意最新主线分支要求在 Ubuntu 22.04 LTS 环境下构建镜像,这需要自行准备。
这里给出一个 patch,把所有 SDK 中可用的 Realtek USB 无线网卡驱动选项都被打开了,顺便把根目录大小提升到 4G。
diff --git a/build/boards/cv180x/cv1800b_milkv_duo_sd/linux/cvitek_cv1800b_milkv_duo_sd_defconfig b/build/boards/cv180x/cv1800b_milkv_duo_sd/linux/cvitek_cv1800b_milkv_duo_sd_defconfig
index 1f387e7cd..c16084651 100644
--- a/build/boards/cv180x/cv1800b_milkv_duo_sd/linux/cvitek_cv1800b_milkv_duo_sd_defconfig
+++ b/build/boards/cv180x/cv1800b_milkv_duo_sd/linux/cvitek_cv1800b_milkv_duo_sd_defconfig
@@ -346,3 +346,23 @@ CONFIG_EPOLL=y
CONFIG_ELF_CORE=y
CONFIG_COREDUMP=y
CONFIG_PROC_SYSCTL=y
+
+# wifi
+CONFIG_CFG80211=y
+CONFIG_WIRELESS=y
+CONFIG_MAC80211=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_RFKILL=y
+
+CONFIG_WLAN=y
+CONFIG_WLAN_VENDOR_REALTEK=y
+
+CONFIG_RTL8187=y
+
+CONFIG_RTLWIFI=y
+CONFIG_RTL8192C_COMMON=y
+CONFIG_RTL8192CU=y
+
+CONFIG_RTL8XXXU=y
+
+CONFIG_RTL8188FU=y
diff --git a/build/boards/cv180x/cv1800b_milkv_duo_sd/memmap.py b/build/boards/cv180x/cv1800b_milkv_duo_sd/memmap.py
index 84161267a..388895702 100644
--- a/build/boards/cv180x/cv1800b_milkv_duo_sd/memmap.py
+++ b/build/boards/cv180x/cv1800b_milkv_duo_sd/memmap.py
@@ -40,7 +40,7 @@ class MemoryMap:
# =================
# Multimedia buffer. Used by u-boot/kernel/FreeRTOS
# =================
- ION_SIZE = 26.80078125 * SIZE_1M
+ ION_SIZE = 0
H26X_BITSTREAM_SIZE = 0 * SIZE_1M
H26X_ENC_BUFF_SIZE = 0
ISP_MEM_BASE_SIZE = 0 * SIZE_1M
diff --git a/device/milkv-duo/genimage.cfg b/device/milkv-duo/genimage.cfg
index 71938363b..943583bd3 100644
--- a/device/milkv-duo/genimage.cfg
+++ b/device/milkv-duo/genimage.cfg
@@ -13,7 +13,7 @@ image rootfs.ext4 {
ext4 {
label = "rootfs"
}
- size = 768M
+ size = 4096M
}
image milkv-duo.img {
注意尽管 staging 目录下有一个 RTL8188EU 驱动,但是是坏的,至少不能驱动 RTL8188EUS。本文最后的章节给出了 RTL8188EUS 可用的树外驱动。
经过测试, RTL8188CU 和 RTL8188FTV 模块都没有问题,板载 type-c 接口配合 OTG 转接头亦可以直接插 RTL8188CU USB 网卡使用。
开始构建镜像,注意如果用普通用户建立镜像需要将 /usr/sbin
加入 PATH
环境变量。
$ export PATH=/usr/sbin:$PATH
$ ./build.sh milkv-duo
INFO: hdimage(milkv-duo.img): writing MBR
gnimage for milkv-duo success!
~/duo-buildroot-sdk/build
~/duo-buildroot-sdk
Create SD image successful: out/milkv-duo-20240327-1236.img
编辑镜像,启用 USB 的主模式,并将 Wifi 连接和 MMDVMHost 启动的脚本放入。
$ sudo mkdir /mnt/sd
$ sudo mount -o loop,offset=134218240 ./duo-buildroot-sdk/out/milkv-duo-20240327-1236.img /mnt/sd
$ rm /mnt/sd/mnt/system/usb.sh
$ ln -sf /mnt/system/usb-host.sh /mnt/sd/mnt/system/usb.sh
$ cp ethtool /mnt/sd/usr/local/bin/
$ mkdir /mnt/sd/opt/MMDVMHost
$ cp MMDVMHost RemoteCommand /mnt/sd/opt/MMDVMHost/
$ vim /mnt/sd/opt/MMDVMHost/start_mmdvm
这里给出 start_mmdvm
脚本的内容,这次将 mmdvm 用户的添加写进了脚本。
#/bin/sh
echo Check Internet Connection
while ! ping -c 1 bing.com 2>&1 > /dev/null; do
sleep 5s
done
echo Check NTP time update
wt=1
while [ `date '+%Y'` = 1970 ]; do
wt=`expr $wt + 1`
if [ $wt -ge 30 ]; then
echo Wait NTP timeout 30s
break
fi
try $wt
sleep 1s
done
if ! grep mmdvm /etc/shadow; then
echo No mmdvm user and group found, add them
addgroup mmdvm
adduser -H -D -S -G mmdvm -s /bin/false mmdvm
fi
echo Start MMDVMHost
[ -d /var/log/mmdvm ] || mkdir /var/log/mmdvm
chown mmdvm:mmdvm /var/log/mmdvm /dev/ttyS4
/opt/MMDVMHost/MMDVMHost
使其可执行。
$ chmod +x /mnt/sd/opt/MMDVMHost/start_mmdvm
建立自启动脚本。
$ vim /mnt/sd/etc/init.d/S99zuser
这里给出脚本内容,主要添加了 Wifi 连接的功能。
#!/bin/sh
${CVI_SHOPTS}
#
# Control eth0 speed and start wpa_supplicant
#
set_network() {
if [ -f /mnt/system/ko/8188eu.ko ]; then
echo Insmod 8188eu.ko
insmod /mnt/system/ko/8188eu.ko
sleep 1s
fi
if /sbin/ip link | grep eth0; then
echo Set eth0 to 10Mbps
ethtool -s eth0 speed 10
fi
if /sbin/ip link | grep wlan0; then
echo Check wifi config
[ -f /etc/wpa_supplicant/wpa_supplicant.conf ] && wpa_supplicant -B -Dnl80211 -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf
fi
}
case "$1" in
start)
set_network 2>&1 > /var/log/mylog
/opt/MMDVMHost/start_mmdvm >> /var/log/mylog &
;;
stop)
;;
restart|reload)
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
这里使用 ethtool 限制有线网络到 10Mbps,主要是自制底板走线不科学导致的连接不稳定。如果 100Mbps 速率下没有发现问题则不需要。
关于 Wifi 配置,尽管默认在 /etc/wpa_supplicant.conf
有一个配置文件,这里并不打算使用它,脚本将根据 /etc/wpa_supplicant/wpa_supplicant.conf
中的配置来启动 wpa_supplicant
。
同样,使其可执行。
$ chmod +x /mnt/sd/etc/init.d/S99zuser
现在可以开始 MMDVMHost 和无线局域网 Wifi 的配置。当然这里并不涉及 MMDVM.ini 的具体内容。
$ cp MMDVM.ini /mnt/sd/etc
$ mkdir /mnt/sd/etc/wpa_supplicant
$ vim /mnt/sd/etc/wpa_supplicant/wpa_supplicant.conf
wpa_supplicant.conf 则可以参考下面的内容。
network={
ssid="youmu46"
psk="youmu464646."
}
至此已经完成,将镜像 dd 到 Micro SD 卡并启动 Milkv Duo。
$ sudo umount /mnt/sd
$ sudo sync
$ sudo sync
$ sudo sync
$ sudo dd if=./duo-buildroot-sdk/out/milkv-duo-20240327-1236.img of=/dev/mmcblk0 bs=4M status=progress
在路由器的管理界面查看是否正常连接,如果没有则连接有线网检查情况。
最后在启动了 MMDVMHost 的情况下查看可用 RAM。
# free -m
total used free shared buff/cache available
Mem: 54 16 26 0 12 35
Swap: 0 0 0
可见非常充裕。
RTL8188EU 驱动
GitHub 现存多个驱动仓库,经过测试有一个确认可用。
$ git clone https://github.com/ivanovborislav/rtl8188eu.git
$ cd rtl8188eu
注意由于是构建内核模块,需要使用和构建镜像相同的工具链,这里是 riscv64-unknown-linux-musl-gcc
,其下载地址可以从 duo-buildroot-sdk 的构建脚本中获知。
首先编辑 Makefile,这里扔一个 patch。
diff --git a/Makefile b/Makefile
index 3d08dac..1398980 100644
--- a/Makefile
+++ b/Makefile
@@ -142,7 +142,7 @@ CONFIG_LAYER2_ROAMING = y
#bit0: ROAM_ON_EXPIRED, #bit1: ROAM_ON_RESUME, #bit2: ROAM_ACTIVE
CONFIG_ROAMING_FLAG = 0x3
###################### Platform Related #######################
-CONFIG_PLATFORM_I386_PC = y
+CONFIG_PLATFORM_I386_PC = n
CONFIG_PLATFORM_RPI_ARM = n
CONFIG_PLATFORM_RPI_ARM64 = n
CONFIG_PLATFORM_ANDROID_X86 = n
@@ -206,6 +206,7 @@ CONFIG_PLATFORM_NV_TK1_UBUNTU = n
CONFIG_PLATFORM_RTL8197D = n
CONFIG_PLATFORM_AML_S905 = n
CONFIG_PLATFORM_ZTE_ZX296716 = n
+CONFIG_PLATFORM_MILKV_DUO = y
########### CUSTOMER ################################
CONFIG_CUSTOMER_HUAWEI_GENERAL = n
@@ -2329,6 +2330,11 @@ endif
endif
+ifeq ($(CONFIG_PLATFORM_MILKV_DUO), y)
+EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
+EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
+endif
+
########### CUSTOMER ################################
ifeq ($(CONFIG_CUSTOMER_HUAWEI_GENERAL), y)
CONFIG_CUSTOMER_HUAWEI = y
构建之。
$ KSRC=~/duo-buildroot-sdk/linux_5.10/build/cv1800b_milkv_duo_sd CROSS_COMPILE=~/duo-buildroot-sdk/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl- make -j4
最后得到 8188eu.ko,将其安装在 Milkv Duo 镜像的 /mnt/system/ko
目录下。前文给出的 S99zuser
脚本在发现该模块存在时将自动载入之。
尾声
至此一个完整且独立的 MMDVM 盒子就完成了。作为手搓的实验版本,已经稳定运行了两周。
这里是桜風の狐,将美好的 73 送上。