收起左侧

明控创能MKC3568开发板研究手记---为无资料支持的板子适配Linux主线内核(Arm飞牛)

2
回复
32
查看
[ 复制链接 ]

1

主题

3

回帖

0

牛值

江湖小虾

项目持续更新中 本文记录的研究成果已整理为开源项目,包含修改后的设备树源文件。欢迎访问 GitHub 仓库获取最新进展: https://github.com/dutyc/IOT-MKC3568-OS-Porting

欢迎访问同步的CSDN文章(文章更新更及时):明控创能MKC3568开发板研究手记——为无资料支持的板子适配Linux主线内核(Arm飞牛)

如果你也拥有同款(或类似)的**开发板,欢迎一起交流、完善。

前言

90块钱能买到什么?对我来说,它开启了一段充满挑战与惊喜的嵌入式探索之旅。

年初看到Arm生态蓬勃发展,决定入手一块开发板亲自体验。在二手平台上,这块明控创能IOT-MKC3568-Main-V1.1(以下简称MKC3568)引起了我的注意——Rockchip RK3568核心,两个千兆网口,两个SATA接口及供电,还有丰富的排针扩展。卖家坦言是项目余料,没有任何官方资料支持。90块钱的价格让我毫不犹豫地下了单,虽然当时并不确定能否让它真正跑起来。

收到板子的头几天,面对陌生的硬件和空白的文档,确实有些无从下手。为了有个参考,我果断又入手了友善电子的NanoPC-T4(RK3399平台),作为学习的参照物。现在看来,这个决定至关重要——它让我理解了什么是“正常”的开发板生态,也让我更有信心去攻克这块“**”板子。

接下来的两个月,是一段充满挑战又足够有趣的旅程:解决OTG接口联机异常、摸索Loader与Maskrom的进入方法、调试主线内核固件的网卡驱动……每一个问题都新奇而棘手,但正是在一天天的文档阅读、代码分析和反复调试中,我慢慢感受到了嵌入式开发的独特魅力。

当第一行内核日志从串口打印出来,当第一个千兆网口成功点亮,那一刻的成就感告诉我:这块90块钱的板子,值了。

谨以此文,记录这段探索之旅,也希望能给同样面对“无资料”开发板的后来者一些参考。

第一章 初识MKC3568:原厂系统与第一道坎

d7ee6ca54272cdb90f1d2609c5f9a48f.png

在收到开发板后,首次上电开机顺利进入原厂预装的Android系统,版本为Android 11 userdebug。尝试通过OTG接口连接电脑进行USB调试时,屏幕上短暂弹出“USB调试已连接”的通知,但仅持续两秒便消失,调试状态随即失效。此后无论更换数据线、切换电脑USB端口,还是反复插拔,均无法再次建立连接。

常规调试路径受阻,我转而考虑ADB无线调试。给开发板插上网线后发现:靠近电源接口的网口可以正常使用,但另一个网口插上后指示灯不亮,DHCP无法获取IP,手动配置也无济于事——这是遇到的第二个问题。好在还有一个可用网口,于是我尝试开启无线调试,但无线调试需要WiFi连接。奇怪的是,系统能搜索到WiFi列表,却始终无法成功连接,即便接上同轴天线也无改善——这是第三个问题。

第二章 另辟蹊径:建立调试通道与系统备份

既然无法通过WiFi开启无线调试,我注意到Android支持使用shell命令强制开启以太网的无线调试(监听5555端口)。虽然这种方法设置的调试状态在重启后会失效,但通过创建一个开机自启服务来执行相关命令,便能获得一个稳定可用的调试通道。

不过,执行这些命令的前提是能够进入系统的shell环境——这需要串口连接。而开发板上的TTL接口是插座形式,我手头没有配套连接线,且排针间距并非标准的2.54毫米,普通杜邦线难以全部插入。即便对杜邦线进行简单处理后勉强插入,连接也极不稳定,串口输出乱码频出。

于是,我决定用烙铁将TTL座子拆下(拆下的座子完好无损,日后可重新焊回),再将公对母杜邦线的**针脚直接焊接在座子的焊盘上。这样一来,一个稳定可靠的串口调试环境便搭建完成了。

IMG_4841-1.JPG

通过串口连接进入安卓的shell控制台后,执行以下命令:

# 提权
su 
# 设置 ADB 监听端口(标准 5555)
setprop service.adb.tcp.port 5555
# 重启 ADB 服务
stop adbd
start adbd
# 验证端口监听
getprop service.adb.tcp.port  # 应返回 5555

# 在电脑上使用 ADB 进行连接
adb connect 开发板IP:5555
# 创建开机自启服务脚本
# 1. 挂载 system 分区为可写
su
mount -o rw,remount /system

# 2. 创建开机自启动脚本
cat > /system/etc/init/99-adb-tcp.rc <<'EOF'
# Automatically enable ADB over TCP on boot
on property:sys.boot_completed=1
    setprop service.adb.tcp.port 5555
    start adbd
EOF

# 3. 设置权限
chown root:root /system/etc/init/99-adb-tcp.rc
chmod 644 /system/etc/init/99-adb-tcp.rc

# 4. 重启生效
sync
reboot

获得ADB调试权限后(得益于userdebug版本的高权限),我立即提取了系统关键分区。通过逆向解包boot.img,获得了内核(kernel)、设备树(dtb)二进制文件及对应的源文件。有了完整的设备树,后续工作总算有了一些基础(当然,真正的挑战还在后面,哈哈)。

通过解包boot.img,初步分析原厂安卓的设备树,结果发现这块开发板是基于rk3568-evb1-ddr4-v10官方评估板设计的。这下就好办了。

/dts-v1/;

/ {
    compatible = "rockchip,rk3568-evb1-ddr4-v10\0rockchip,rk3568";
    interrupt-parent = <0x01>;
    #address-cells = <0x02>;
    #size-cells = <0x02>;
    model = "Rockchip RK3568 EVB1 DDR4 V10 Board";

此时,我们需要对这块开发板的现状进行冷静评估:功能极不稳定,没有现成固件,没有原厂支持,甚至连loader和maskrom模式都无法进入。原厂安卓系统就是我们当前最宝贵的第一手资料,必须对其进行深度探索,收集足够信息,才能推进后续研究。

正因如此,对原厂安卓系统进行完整备份显得尤为重要。我接上U盘,使用 dd命令将整个EMMC打包为.img格式的RAW硬盘镜像。这样一来,日后若能进入loader或maskrom模式,便可随时将备份写回。

# 备份分区
rk3568_r:/storage/CE3297AB329796D5 # cd backup/
dd if=/dev/block/mmcblk2 of=/storage/CE3297AB329796D5/backup/rk3568_android_full.img bs=4M conv=sync,noerror    
7488+0 records in
7488+0 records out
31406948352 bytes (29 G) copied, 2087.845889 s, 14 M/s
rk3568_r:/storage/CE3297AB329796D5/backup #

70af77149423fdb57e8dd8f5c5173a35.png

第三章 深入引导层:OTG困境与GSI转机

在学习完内核相关知识后,我决定深入探究引导层。然而OTG接口无法联机的问题依然存在:无论按下V+键、U-boot组合键,还是RESET、POWER键上电,电脑均无法识别设备。按下RESET键后系统卡在Rockchip Logo界面,串口输出显示RKUSB进度条转动,说明bootloader尝试与电脑通信,但最终因OTG接口故障而失败。我曾尝试短接EMMC的CLK引脚以强制进入Maskrom模式,但主板上找不到对应引脚。对比Rockchip官方EVB参考板的电路图,布局差异太大,无法获得有效线索。

一次偶然的机会,我在开发者选项中发现了“DSU”(动态系统更新)功能,即刷入GSI(通用系统镜像)。虽然GSI也是基于userdebug的通用系统,不一定能带来更多信息,但鉴于板子上已无其他亮点功能可探索,我决定刷入一个带有Google Play框架的Android 12 GSI镜像,权当一试。

重启进入GSI后,简单过完OOBE设置。由于OTG线一直连接着,我照常开启USB调试,奇迹出现了:授权对话框弹出,同意后电脑立即识别出板载存储,设备名显示为“GSI on Arm64”,ADB连接成功!USB调试终于恢复正常。一番摸索后,直接拔电再上电,进入安卓后使用ADB命令成功将设备引导至loader模式,进而通过RKdevtool进入loader模式,随后又切换回Maskrom模式。

adb reboot loader

此时,我们需要重新审视当前的进展:我们是通过软件层面的 reboot loader命令进入的loader和maskrom模式。一旦后续刷入Linux系统,这条命令将不复存在。届时若再想进入底层模式,就必须依赖硬件按键组合或短接触点——而这两种方式在当前板子上都存在问题。

因此,一个兼容性良好、能稳定引导进入系统的主线Linux固件,就显得尤为重要。它是让开发板跑起来,后续调试和维护的根基。

第四章 进军主线:飞牛系统适配之路

适配主线内核固件的工作量较大,我最终选择了现成的Arm飞牛系统进行适配,而非从零编译。选择飞牛而非Armbian等成熟固件,主要基于两点考量:一是飞牛采用了更新的内核(kernel 6.12.41);二是其出色的硬件兼容性——在我的Nano PC-T4上,飞牛能正常识别傲腾M10 16GB固态硬盘,而友善官方固件及其他系统则无法识别该硬盘(其他NVMe硬盘可正常识别)

飞牛固件中已包含大量预置的设备树,其中就包括 rk3568-evb1-v10.dtb,这是 Rockchip 官方 RK3568 EVB1 评估板的设备树. 所以我们的任务是对飞牛固件进行修改,将启动时的设备树指向这个文件。

但此时我面临一个两难:如果直接使用这个公版设备树,万一与原厂硬件存在差异,系统可能无法启动;可若从零编写一个专属设备树,又需要花费大量时间反复试验——而这块开发板目前唯一的可引导系统就是我即将刷入的飞牛固件,一旦失败,没有其他系统可以回退(loader模式暂时无法从硬件层面进入)

为了将风险降到最低,我决定先做一次对比验证:将****原厂安卓设备树主线内核中自带的 rk3568-evb1-v10.dtb 进行了逐项比对。结果发现,两者高度相似——原厂设备树明显基于 Rockchip 官方 EVB1 公版设计,主线内核的公版设备树则包含了 EVB1 的基础定义,仅缺失了明控创能为自家开发板增加的定制节点。这意味着,直接让飞牛使用 rk3568-evb1-v10.dtb 至少能够保证 Linux 内核正常启动。

image-20260321210047287.png

**有了这个对比结论,我决定冒一次险,将设备树指向 **rk3568-evb1-v10.dtb。这里以友善 R5S(同样是基于 RK3568 平台)的固件为基础进行改造。

[基石]固件修改:让系统认识MKC3568

在Ubuntu开发机上对固件镜像文件 fnos_Mainland-PE_arm_1.0.0_nanopi-r5s_249.img进行操作:

# 安装依赖
sudo apt-get update
sudo apt-get install kpartx qemu-user-static binutils mount e2fsprogs erofs-utils squashfs-tools

# 创建回环设备
sudo losetup -f --show fnos_Mainland-PE_arm_1.0.0_nanopi-r5s_249.img
# 输出示例:/dev/loop13

# 映射分区
sudo kpartx -av /dev/loop13

# 挂载第一个分区(p1)
sudo mkdir -p /mnt/fn_mount
sudo mount /dev/mapper/loop13p1 /mnt/fn_mount

编辑 /mnt/fn_mount/fnEnv.txt,将设备树指向 rk3568-evb1-v10.dtb

verbosity=1
bootlogo=false
console=both
extraargs=cma=256M
fdtfile=rockchip/rk3568-evb1-v10.dtb

修改完成后卸载分区并清理:

sudo umount /mnt/fn_mount
sudo kpartx -d /dev/loop13
sudo losetup -d /dev/loop13

让开发板进入loader模式,将修改后的固件刷入。注意在刷写工具中只勾选 System一栏(地址 0x00000000),并勾选 强制按地址写选项。

飞牛的引导链与其他固件一致。在loader模式下刷入固件后,通过串口观察启动日志,看到一行行“OK”顺利通过,最终飞牛系统成功启动。这一次冒险成功了!

fd36cacd7b03ed7da1f2d666690dc610.png

4.1 初入系统:网口失效的困境

重启后系统虽正常启动,但网口指示灯不亮。此时飞牛系统尚未完成初始化,用户账号密码均未设置.

几番尝试后,我猜出了飞牛的默认凭据(我只能确认R5S的1.0.0版本的arm飞牛固件是这个密码,其他固件可能有变动):用户名 root,密码也是 root(与用户名相同)。成功登录后,迫不及待地检查网络状态:

root@MKC3568:/$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
2: end1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
3: end0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0

两个千兆网口(end0和end1)均处于未连接状态。虽然系统成功启动,但设备树的适配工作才刚刚开始——网口驱动的调试注定是一场持久战。

4.2 另寻出路:USB网络共享

网口不能用,但开发和测试工作不能停。我手头有一块 MT7601U芯片的 USB无线网卡,如果能驱动起来,至少能让开发板联网。然而飞牛系统并未编译MT7601U模块:

root@MKC3568:/# uname -a
Linux MKC3568 6.12.41-trim #1 SMP PREEMPT Wed Dec 31 02:09:11 UTC 2025 aarch64 GNU/Linux

root@MKC3568:/# sudo modprobe mt7601u
modprobe: FATAL: Module mt7601u not found in directory /lib/modules/6.12.41-trim

Linux内核从v4.2开始已将mt7601u驱动合并进主线(位于 drivers/net/wireless/mediatek/mt7601u/),但飞牛的内核镜像未包含该无线驱动模块。这意味着需要自行编译内核模块。

编译内核模块需要下载源码,这又依赖网络连接——这是一个经典的"先有**还是先有蛋"问题。好在安卓手机的USB网络共享功能解决了这个困境,用数据线将开发板的USB-HOST口与手机连接,开启USB网络共享,开发板便顺利接入互联网。这一功能的兼容性出奇地好,为后续工作打开了通路。

4.3 内核模块编译:MT7601U驱动

4.3.1 下载内核源码

编译内核模块需要与当前运行内核完全匹配的源码版本:

mkdir /home/kernel
cd /home/kernel

# 克隆时直接指定tag v6.12.41(深度为1,只下载该版本)
git clone --depth=1 --branch v6.12.41 https://mirrors.tuna.tsinghua.edu.cn/git/linux-stable.git

cd linux

为什么使用内核源码中的驱动?

选择与当前运行内核同版本的内核源码编译mt7601u驱动,是为了保证模块的vermagic、配置和符号表与系统完全一致,从而避免加载失败。主线代码经过充分测试,与内核其他组件兼容性最佳,还能直接复用/proc/config.gz的配置,省去手动调整依赖的麻烦。日后内核升级时,只需用相同方法重新编译对应版本即可,维护十分方便。而第三方GitHub仓库中的驱动往往包含未经验证的补丁,不仅容易引发兼容性问题,也难以跟随内核同步更新。

4.3.2配置编译环境

确认系统中有 /proc/config.gz配置文件——这个文件很关键,飞牛内核带有 -trim后缀:

root@MKC3568:/home/kernel/linux# ls /proc/config.gz
/proc/config.gz

直接在Arm平台上原生编译,不需要交叉编译器。首先安装编译工具链:

apt update
apt install -y build-essential flex bison libssl-dev libelf-dev bc

设置编译参数:

# 设置编译架构(必须设置!否则可能编译出错误架构的模块)
export ARCH=arm64
export CROSS_COMPILE=

# 使用系统当前的内核配置
zcat /proc/config.gz > .config

# 添加正确的LOCALVERSION
echo 'CONFIG_LOCALVERSION="-trim"' >> .config

# 强制启用MT7601U驱动为模块
echo 'CONFI**T7601U=m' >> .config

# 自动处理依赖和新选项
make olddefconfig

准备构建环境:

make modules_prepare

4.3.3编译mt7601u模块

KBUILD_MODPOST_WARN=1 make M=drivers/net/wireless/mediatek/mt7601u modules

为什么加KBUILD_MODPOST_WARN=1?

make modules_prepare只准备了头文件,不会生成完整的 Module.symvers(需要完整编译内核才会生成),因此直接编译外部模块会因找不到符号验证文件而报错。但mt7601u是独立模块,不依赖其他内核模块,且源码和 .config与当前内核完全匹配,那些“未定义符号”实际都存在于内核中。加上 KBUILD_MODPOST_WARN=1可将错误降级为警告,从而正常生成 .ko文件。

4.3.3验证并安装模块

编译完成后,模块位于 drivers/net/wireless/mediatek/mt7601u/mt7601u.ko。验证模块的vermagic:

modinfo drivers/net/wireless/mediatek/mt7601u/mt7601u.ko | grep vermagic

正常应输出:

vermagic: 6.12.41-trim SMP preempt mod_unload aarch64

与系统内核版本完全匹配。然后安装并加载驱动:

# 1. 创建目标目录
sudo mkdir -p /lib/modules/$(uname -r)/kernel/drivers/net/wireless/mediatek/mt7601u/

# 2. 备份原有模块(如果有)
sudo cp /lib/modules/$(uname -r)/kernel/drivers/net/wireless/mediatek/mt7601u/mt7601u.ko ~/mt7601u-6.12.41-trim.ko.bak 2>/dev/null || true

# 3. 复制新编译的模块
sudo cp drivers/net/wireless/mediatek/mt7601u/mt7601u.ko \
   /lib/modules/$(uname -r)/kernel/drivers/net/wireless/mediatek/mt7601u/

# 4. 更新模块依赖
sudo depmod -a

# 5. 安装固件
sudo mkdir -p /lib/firmware/mediatek/
sudo wget -O /lib/firmware/mediatek/mt7601u.bin \
   https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/mediatek/mt7601u.bin
sudo cp /lib/firmware/mediatek/mt7601u.bin /lib/firmware/

# 6. 加载驱动
sudo modprobe mt7601u

插入USB无线网卡,观察内核日志:

root@MKC3568:/home/kernel/linux# dmesg | tail -20
mt7601u 1-1:1.0: ASIC revision: 76010001 ...
mt7601u 1-1:1.0: Firmware Version: 0.1.00

通过 ip link show可以看到无线接口 wlx90de80624b0c。飞牛默认使用NetworkManager,连接Wi-Fi:

sudo nmcli dev wifi connect "你的Wi-Fi名称" password "你的Wi-Fi密码"

设置开机自动加载模块:

echo "mt7601u" | sudo tee /etc/modules-load.d/mt7601u.conf

有了无线网络,开发板终于可以正常访问互联网,为后续的网口驱动调试铺平了道路。

4.4更新后的模块维护

在使用过程中,飞牛收到了新版本的OTA推送。更新后发现自行编译并加载的mt7601u模块消失——内核升级后,原模块自然不再适用。不必紧张,只需用相同方法重新编译新内核对应的驱动即可。

建议将编译好的模块备份到安全位置(如 /home/backup/目录),以便快速恢复:

sudo mkdir -p /lib/modules/$(uname -r)/kernel/drivers/net/wireless/mediatek/mt7601u/
sudo cp drivers/net/wireless/mediatek/mt7601u/mt7601u.ko \
   /lib/modules/$(uname -r)/kernel/drivers/net/wireless/mediatek/mt7601u/
sudo depmod -a
sudo modprobe mt7601u

掌握内核模块编译方法,相当于获得了为任何内核版本定制驱动的能力,这对于长期维护一个无资料的开发板至关重要。

6ded57cd93a2b109df48ee556651b3fb-1.png

4.5 设备树精修:攻克网口驱动

借助USB无线网卡临时打通网络后,我终于可以专注解决核心问题——让板载的两个千兆网口正常工作。有了之前从原厂安卓系统提取的设备树作为参照,我开始逐项对比飞牛设备树与安卓设备树的差异,一步步定位问题根源。

4.5.1 问题定位:MDIO 无响应

**首先确认网口硬件是否被内核识别。使用 **phytool 扫描 MDIO 总线,结果令人沮丧——所有地址均返回 -19,说明 PHY 芯片根本没有响应:

root@MKC3568:/home/dutyc/phytool# ./phytool read stmmac-0/1/0x0
error: phy_read (-19)

**手动复位 GPIO 后问题依旧,且所有 MDIO 地址均无响应。这指向两种可能:PHY 芯片未正常工作,或 MDIO 引脚配置有误。对比原厂安卓和飞牛的 **pinctrl 配置,两者完全一致,因此引脚配置无误。问题很可能出在设备树的其他关键参数上。

4.5.2 深度对比:原厂安卓 vs 飞牛设备树

**我将原厂安卓的 **ethernet@fe010000 节点(对应 end1)与飞牛的同一节点进行了逐项对比,梳理出以下关键差异:

配置项 原厂安卓 飞牛 差异分析
phy-mode rgmii rgmii-id RGMII 接口的延迟提供方式不同。rgmii-id依赖 PHY 内部延迟,而 rgmii需要 MAC 或 PCB 布线提供延迟。两者不匹配会导致数据时序错乱。
tx_delay / rx_delay 有(0x4f / 0x26) 当使用 rgmii模式时,这两个参数用于调整 MAC 内部的发送/接收时钟延迟。缺失会导致时序无法对齐。
复位方式 MAC 节点内 snps,reset-gpio PHY 节点内 reset-gpios 两种方式均可,但内核驱动处理路径不同。原厂安卓的配置已在硬件上验证有效。
assigned-clock-parents 两个父节点 一个父节点 缺少第二个父节点可能导致参考时钟的时钟源配置不完整,影响时钟输出。
时钟数量 9 个 10 个(多 clk_xpcs_eee 飞牛内核可能启用了 XPCS 的 EEE 功能,需要额外时钟,应予以保留。

4.5.3 原厂安卓 gmac1 节点完整解析

**原厂安卓的 **ethernet@fe010000 节点配置如下(已标注关键部分):

ethernet@fe010000 {
    compatible = "rockchip,rk3568-gmac\0snps,dwmac-4.20a";
    reg = <0x00 0xfe010000 0x00 0x10000>;
    interrupts = <0x00 0x20 0x04 0x00 0x1d 0x04>;
    interrupt-names = "macirq\0eth_wake_irq";
    rockchip,grf = <0x33>;                    // GRF模块phandle
    clocks = <0x1f 0x186 0x1f 0x189 0x1f 0x189 0x1f 0xc7 0x1f 0xc3 0x1f 0xc4 0x1f 0x189 0x1f 0xc8 0x1f 0xac>;
    clock-names = "stmmaceth", "mac_clk_rx", "mac_clk_tx", "clk_mac_refout", "aclk_mac", "pclk_mac", "clk_mac_speed", "ptp_ref", "pclk_xpcs";
    resets = <0x1f 0xec>;
    reset-names = "stmmaceth";
    snps,mixed-burst;
    snps,tso;
    snps,axi-config = <0x7b>;
    snps,mtl-rx-config = <0x7c>;
    snps,mtl-tx-config = <0x7d>;
    status = "okay";
    phy-mode = "rgmii";                        // 关键:使用rgmii模式
    clock_in_out = "output";
    // 关键:MAC节点内复位,使用gpio2偏移25(0x19),低有效
    snps,reset-gpio = <0x7e 0x19 0x01>;        // 0x7e是gpio2的phandle
    snps,reset-active-low;
    snps,reset-delays-us = <0x00 0x4e20 0x186a0>;
    // 关键:两个时钟父节点
    assigned-clocks = <0x1f 0x189 0x1f 0x186>;
    assigned-clock-parents = <0x1f 0x187 0x1f 0xc5>;  // 两个父节点
    assigned-clock-rates = <0x00 0x7735940>;
    pinctrl-names = "default";
    pinctrl-0 = <0x7f 0x80 0x81 0x82 0x83>;    // gmac1引脚复用
    // 关键:tx_delay和rx_delay参数
    tx_delay = <0x4f>;
    rx_delay = <0x26>;
    phy-handle = <0x84>;

    mdio {
        compatible = "snps,dwmac-mdio";
        #address-cells = <0x01>;
        #size-cells = <0x00>;

        phy@0 {
            compatible = "ethernet-phy-ieee802.3-c22";
            reg = <0x00>;                        // PHY地址为0
            phandle = <0x84>;
        };
    };
    // ... 省略子节点配置
};

4.5.4 飞牛 gmac1 节点改造方案

**基于上述对比,我确定了飞牛 **ethernet@fe010000 节点的改造方案,遵循以下原则:

  • 保留飞牛额外的时钟clk_xpcs_eee),因为飞牛内核可能需要它
  • 添加第二个时钟父节点,与原厂安卓保持一致
  • 将复位方式从 PHY 节点移至 MAC 节点,采用原厂安卓已验证的风格
  • 修改 phy-modergmii,并补上 tx_delay / rx_delay 参数
  • 删除 PHY 节点内的复位属性,避免冲突

改造后的节点如下(关键修改处已加注释):

ethernet@fe010000 {
    compatible = "rockchip,rk3568-gmac", "snps,dwmac-4.20a";
    reg = <0x00 0xfe010000 0x00 0x10000>;
    interrupts = <0x00 0x20 0x04 0x00 0x1d 0x04>;
    interrupt-names = "macirq", "eth_wake_irq";
    // 保留飞牛的10个时钟(比原厂多一个clk_xpcs_eee)
    clocks = <0x12 0x186 0x12 0x189 0x12 0x189 0x12 0xc7 0x12 0xc3 0x12 0xc4 0x12 0x189 0x12 0xc8 0x12 0xac 0x12 0xab>;
    clock-names = "stmmaceth", "mac_clk_rx", "mac_clk_tx", "clk_mac_refout", "aclk_mac", "pclk_mac", "clk_mac_speed", "ptp_ref", "pclk_xpcs", "clk_xpcs_eee";
    resets = <0x12 0xec>;
    reset-names = "stmmaceth";
    rockchip,grf = <0x23>;                       // 飞牛grf phandle
    snps,axi-config = <0x4e>;                     // 保留飞牛原有phandle
    snps,mixed-burst;
    snps,mtl-rx-config = <0x4f>;
    snps,mtl-tx-config = <0x50>;
    snps,tso;
    status = "okay";
    // 添加第二个时钟父节点(原厂安卓风格)
    assigned-clocks = <0x12 0x189 0x12 0x186>;
    assigned-clock-parents = <0x12 0x187 0x12 0xc5>;  // 添加第二个父节点
    assigned-clock-rates = <0x00 0x7735940>;
    clock_in_out = "output";
    phy-handle = <0x51>;
    // 关键修改:phy-mode从rgmii-id改为rgmii
    phy-mode = "rgmii";
    // 添加原厂安卓的tx_delay和rx_delay
    tx_delay = <0x4f>;
    rx_delay = <0x26>;
    // 添加MAC节点复位属性(原厂安卓风格)
    // 使用飞牛gpio2的phandle 0x57,偏移0x19,低有效
    snps,reset-gpio = <0x57 0x19 0x01>;
    snps,reset-active-low;
    snps,reset-delays-us = <0x00 0x4e20 0x186a0>;
    // 保持飞牛原有的pinctrl配置
    pinctrl-names = "default";
    pinctrl-0 = <0x52 0x53 0x54 0x55 0x56>;

    mdio {
        compatible = "snps,dwmac-mdio";
        #address-cells = <0x01>;
        #size-cells = <0x00>;

        ethernet-phy@0 {
            compatible = "ethernet-phy-ieee802.3-c22";
            reg = <0x00>;
            // 删除reset-gpios、reset-assert-us、reset-deassert-us
            phandle = <0x51>;
        };
    };
    // ... stmmac-axi-config等子节点保持不变
};

关于第二个网口(gmac0)的说明 ** **对于 ethernet@fe2a0000 节点,我采用了相同的改造思路(原厂安卓中该节点的复位引脚为 GPIO2 偏移 27,tx_delay / rx_delay 分别为 0x3c0x2f)。但经测试,该网口在原厂安卓下本就处于无法使用的状态,硬件层面可能存在缺陷,因此暂未修复。目前先集中精力让一个网口稳定工作。

4.5.5 编译验证

完成设备树修改后,我将其编译为独立的 dtb 文件并替换系统默认配置:

mkdir /home/kerneldtb
cd /home/kernel-dtb
# 克隆与当前内核版本完全匹配的源码
git clone --depth=1 --branch v6.12.41 https://mirrors.tuna.tsinghua.edu.cn/git/linux-stable.git

cd linux
cp /lib/modules/$(uname -r)/build/Module.symvers ./Module.symvers
cp /boot/config-6.12.41-trim ./.config

**将修改后的设备树源文件 **rk3568-mkc-main.dts 放入 arch/arm64/boot/dts/rockchip/ 目录,并在同目录的 Makefile 中添加编译目标:

dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-mkc-main.dtb

开始编译:

make ARCH=arm64 dtbs -j`nproc`

**编译完成后,将生成的 **rk3568-mkc-main.dtb 复制到 /boot/dtb/rockchip/ 目录,并修改 /boot/fnEnv.txt 中的 fdtfile 指向新设备树:

verbosity=1
bootlogo=false
console=both
extraargs=cma=256M
fdtfile=rockchip/rk3568-mkc-main.dtb

重启后,奇迹发生了——end1 成功获取到 IP 地址:

dutyc@MKC3568:~$ ip a
3: end1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 192.168.1.170/24 brd 192.168.1.255 scope global dynamic end1

虽然第二个网口因硬件问题暂未修复,但 end1 的成功已经让这块开发板具备了完整的 NAS 功能。

这一刻,这块 90 块钱的板子,活了。

第五章 当前状态与未尽之事

目前,end1已经稳定工作,可以通过它访问飞牛NAS的所有功能。但第二个网口(end0)在原厂安卓下本就无法使用,硬件层面可能存在问题,暂未修复。另外,修复end1的过程中可能引发了引脚冲突,导致TF卡槽暂时无法识别,还需进一步调试。

尽管仍有瑕疵,但核心目标——让这块“无资料”的开发板运行主线内核并具备NAS功能——已经达成。接下来的日子里,我会继续完善它,也让这份手记随着探索不断丰富。

后记

两个月的入门,一块90块钱的板子,无数个debug的深夜。有人问:“买个没资料的开发板干什么?”现在,我可以回答:正因为没资料,才需要有人去试. 它让我学会了逆向、设备树、内核调试,让我亲手点亮了一个原本可能被废弃的硬件。这份收获,远不止90块钱。

谨以此文,纪念这段与MKC3568共度的时光。也感谢Qwen和Deepseek在技术探索中提供的帮助。


(未完待续……)

研究参考文章列表

开发板与固件资源

系统移植与定制

SDK 与编译环境

烧录与调试方法

硬件与芯片资料

其他相关技术文章

收藏
送赞 1
分享

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

7

主题

18

回帖

0

牛值

江湖小虾

真大佬,不明觉厉

17

主题

203

回帖

355

牛值

社区共建团

社区共建团荣誉勋章飞牛百度网盘玩家fnOS1.0上线纪念勋章EVO2产品纪念

很多板子都基于现有方案修修改改出来的,这种还是稍微好弄一点的

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则