项目持续更新中 本文记录的研究成果已整理为开源项目,包含修改后的设备树源文件。欢迎访问 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:原厂系统与第一道坎

在收到开发板后,首次上电开机顺利进入原厂预装的Android系统,版本为Android 11 userdebug。尝试通过OTG接口连接电脑进行USB调试时,屏幕上短暂弹出“USB调试已连接”的通知,但仅持续两秒便消失,调试状态随即失效。此后无论更换数据线、切换电脑USB端口,还是反复插拔,均无法再次建立连接。
常规调试路径受阻,我转而考虑ADB无线调试。给开发板插上网线后发现:靠近电源接口的网口可以正常使用,但另一个网口插上后指示灯不亮,DHCP无法获取IP,手动配置也无济于事——这是遇到的第二个问题。好在还有一个可用网口,于是我尝试开启无线调试,但无线调试需要WiFi连接。奇怪的是,系统能搜索到WiFi列表,却始终无法成功连接,即便接上同轴天线也无改善——这是第三个问题。
第二章 另辟蹊径:建立调试通道与系统备份
既然无法通过WiFi开启无线调试,我注意到Android支持使用shell命令强制开启以太网的无线调试(监听5555端口)。虽然这种方法设置的调试状态在重启后会失效,但通过创建一个开机自启服务来执行相关命令,便能获得一个稳定可用的调试通道。
不过,执行这些命令的前提是能够进入系统的shell环境——这需要串口连接。而开发板上的TTL接口是插座形式,我手头没有配套连接线,且排针间距并非标准的2.54毫米,普通杜邦线难以全部插入。即便对杜邦线进行简单处理后勉强插入,连接也极不稳定,串口输出乱码频出。
于是,我决定用烙铁将TTL座子拆下(拆下的座子完好无损,日后可重新焊回),再将公对母杜邦线的**针脚直接焊接在座子的焊盘上。这样一来,一个稳定可靠的串口调试环境便搭建完成了。

通过串口连接进入安卓的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 #

第三章 深入引导层: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 内核正常启动。

**有了这个对比结论,我决定冒一次险,将设备树指向 **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”顺利通过,最终飞牛系统成功启动。这一次冒险成功了!

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

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-mode 为 rgmii,并补上 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 分别为 0x3c 和 0x2f)。但经测试,该网口在原厂安卓下本就处于无法使用的状态,硬件层面可能存在缺陷,因此暂未修复。目前先集中精力让一个网口稳定工作。
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 与编译环境
烧录与调试方法
硬件与芯片资料
其他相关技术文章