ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

RK3576嵌入式Linux底板开发踩坑实录:从硬件设计到启动调试

RK3576嵌入式Linux底板开发踩坑实录:从硬件设计到启动调试 最近把一块自研 RK3576 底板的项目交付了才终于有底气坐下来写这篇复盘。标题里说“踩坑”其实是客气话因为这个过程踩进去的坑多到让人怀疑人生光 U-Boot 启动参数和 USB 枚举就各耗掉差不多两天。RK3576 这颗料在规格书上确实诱人A72A53 大小核组合、集成 NPU、DDR 支持到 LPDDR5接口也齐全非常适合做嵌入式 Linux 项目里的工业 HMI、边缘计算网关、NAS 或者视觉检测盒子。但“看片”和“玩机”是两回事真把它焊到PCB上、写好设备树、调通一条完整链路背后的细节比官方案例隐藏的多得多。我这次项目是一台 8 寸屏的工业人机交互设备外加两路 USB 摄像头、一个千兆网口、若干 RS485操作系统用的嵌入式 Linux启动盘从 NFS 调试阶段一直切到 eMMC 固化阶段。整个过程中涉及 RK3576 硬件设计资料、SDK 编译、USB 驱动、显示链路、系统烧写和根文件系统挂载一堆环节。这篇就按我实际踩坑的顺序来写每个章节都会说清楚当时的现象、排查路径和最终的解决方式尽量不给纯理论只讲能直接抄作业的东西。1. 选型阶段就埋雷核心板和底板别想得太简单1.1 为什么不是 RK3588也不是 RK3566项目需求摆出来之后第一个问题就是选主控。工程师最忌讳的就是上来就写代码硬件选型才是后面所有工作的地基。我在 RK3588、RK3566 和 RK3576 之间比了很久最终选了 RK3576不是因为便宜而是因为它正好卡在性能和功耗的甜点上。RK3588 的性能确实强悍8 核 A76A55但功耗和 PCB 设计要求也高四路 MIPI CSI 和复杂供电对两层板来说直接是灾难我们这板子体积受限还要做宽温工业级RK3588 散热和物料成本都会超支。RK3566 倒是省心省钱但它的 A55 核心在跑中等负载视觉算法时明显吃力内存带宽和 PCIe 扩展性也不够将来做往上堆算力的版本会很痛苦。RK3576 的 A72A53 大小核组合比 A55 平台强一截NPU 算力也够跑常见分类模型和简单检测模型同时功耗、DDR 布线难度、PMIC 配套复杂度都在可控范围。对我这个级别的项目来说这是典型“多一分浪费、少一分不够”的答案。但选好芯片只是开始后面的硬件设计才是第一道坎。1.2 RK3576 硬件设计资料的正确打开方式官方 RK3576 硬件设计资料下载下来之后大多数人会先去看参考原理图和 PCB这个方向没错但很容易踩到两个隐蔽坑一是参考设计可能是针对官方 EVB 的物料型号和引脚分配并不一定适合你的量产板二是电源树和 PMIC 配置被很多人直接照抄结果上电顺序不对。我给 RK3576 做电源设计时排查过最诡异的一个问题板子静态电流正常但反复上电五次里有一次系统完全死掉量各路电压又都没问题最后才发现是 PMIC 的默认上下电时序和核心电压、DDR 电压之间的配合没按 TRM 时序要求来。RK3576 的电源轨多SOC 内核、逻辑、IO、DDR 的电源要求和相互之间的延迟约束分得很细特别是 DDR 电源必须在核心电压稳定之后再起来这个顺序不能反。如果你是自己画底板而不是买现成核心板强烈建议把 RK3576 PMIC 的 datasheet 和 SoC 的 Power Domain 章节打印出来对照着看别只看 EVB 的原理图。每一路上面的电容容量、纹波要求都要过一遍有些低压大电流的轨并的电容不够后果就是系统在重载时随机复位查起来比软件 bug 烧脑得多。1.3 DDR 颗粒配置可不是焊上去就能跑RK3576 对 DDR 的支持是 LPDDR4、LPDDR4X、LPDDR5听起来灵活实际调试时颗粒频率和参数直接决定你能否开机进 U-Boot。我第一次打样用的是批量好买的 LPDDR4X 颗粒RK3576 的 DDR 初始化在 U-Boot 里会检测颗粒型号并自动读取配置文件。如果颗粒不在调试好的列表里有可能跳过某些时序参数导致内存测试正常但跑应用负载时偶发 watchdog 复位。DDR 相关的坑还有 PCB 走线RK3576 的 DDR 接口速率高原理图可以照抄但 PCB 布线里的等长、参考平面、过孔不能糊弄。我在第一版 PCB 里用的是四层板标准叠层未按官方建议的六层做结果 U-Boot 可以起来但进入内核后解压 kernel 偶尔失败。这种问题最容易发生在“看起来能用实际很勉强”的状态。A 版本打样可以在走线上多预留冗余如果要做量产叠层阻抗和长度匹配一定要按设计指南来不要想省层数。”2. SDK 编译环境拉代码开始就全是坎2.1 repo 版本混乱SDK到底怎么选Rockchip 官方的 SDK 是用 repo 管理的包含 U-Boot、kernel、buildroot、debian、prebuilt 工具链等众多仓库。第一次拉取时最容易犯的错是直接repo sync默认分支没有核对内核版本和芯片支持情况。RK3576 的适配代码在不同分支上差异很大有些分支 U-Boot 是旧版有些内核的 defconfig 还是早期的。我项目上用到的 RK3576 内核代码一开始是从厂商仓库同步的结果发现linux/arch/arm64/boot/dts/rockchip/rk3576-evb.dts这个文件版本太老连 USB 3.0 节点名字都跟实际硬件不匹配。后来我干脆用repo init -m rk3576.xml指定了对应芯片的 manifest重新同步。如果你们公司没有配置内部镜像仓库团队多人同时repo sync会非常慢而且经常中断。这种情况我建议至少拉一次完整 SDK 后打包成 tar 放到本地服务器。2.2 编译工具链和宿主系统的恩怨RK3576 的 SDK 默认需要 Ubuntu 18.04 或 20.04如果你用较新的发行版比如 Ubuntu 22.04/24.04编译 U-Boot 和内核时大概率会遇到各种库路径和依赖问题。我当时用的编译机是 Ubuntu 22.04第一次执行./make.sh rk3576时脚本直接报错找不到lib32ncurses5之类的依赖。装了半天兼容库之后又遇到 Python 脚本语法不兼容的问题。最终我选择在编译机上跑一个 Ubuntu 20.04 的 Docker 容器把整个 SDK 放进容器里编译这样最省心。如果你不想折腾容器也可以把 SDK 工具链里自带的交叉编译器路径手动加进 PATH然后用export ARCHarm64、export CROSS_COMPILEaarch64-linux-gnu-来编译内核。需要特别注意的是SDK 预置的工具链版本是有讲究的不要随手拿/usr/bin/aarch64-linux-gnu-gcc去替代gcc 版本不同会导致内核模块的 ABI 不兼容最常见的问题就是外挂驱动编译时modpost一堆告警加载模块时直接disagrees about version of symbol。2.3 根文件系统挂载的坑NFSv3 的漫长排查这应该是我这次项目里最值得写的一段。嵌入式 Linux 开发阶段大家普遍用 NFS 做根文件系统省去反复烧写存储介质的时间。RK3576 的 U-Boot 里默认支持 NFS但内核里的 NFS 客户端默认配置却可能不满足你的需求。现象是U-Boot 通过nfs命令可以加载内核内核起来后却一直卡在VFS: Unable to mount root fs via NFS。我一开始怀疑是网络驱动问题反复查eth0有没有 link后来才发现问题出在 NFS 版本上。RK3576 内核默认开启的 NFS 客户端支持版本主要是 v4而我在服务器上搭建 NFS 服务时用的默认配置是 v4 导出U-Boot 在内核命令行里却写的是nfsroot192.168.1.10:/srv/nfs,vers3。对 NFSv3 的请求服务器那个导出路径如果没有显式vers3支持就会挂载失败。更隐蔽的是网络传输大文件时 UDP 模式的 NFS 不稳定我在 bootargs 里必须加nfsroot192.168.1.10:/srv/nfs,vers3,tcp同时给内核传ip192.168.1.20:::::eth0:off。这里有个经验点如果你看到内核 log 里一直重复NFS: nfs4_discover_server_list之类的内容但没进展优先怀疑服务器导出版本和 TCP/UDP 协议栈而不是去改内核配置。根文件系统挂载这种环境题往往不是板子的问题而是服务器配置的参数不一致。3. RK3576 USB 调试从完全没反应到稳定运行3.1 USB 3.0 高速信号的枚举失败我项目板子上有两路 USB 3.0其中一路接摄像头模块。一开始拿到板子插上 USB 3.0 设备系统完全识别不了dmesg只显示usb 2-1: new high-speed USB device number 8但枚举大概率超时。这个问题的排查点有两类一是硬件层面差分线阻抗、等长和参考平面二是软件层面 USB 3.0 的掩码和电源控制。我先量了差分线发现 USB 3.0 TX/RX 从 SoC 到连接器的走线长了且中间串了不少过孔回波损耗和串扰都可能让接收端眼图张不开。RK3576 的 USB PHY 对信号质量并不“宽容”不像 USB 2.0 那样稍微差一点还能勉强跑。后来我重新设计了连接器附近的走线尽量保证差分对内等长并在 USB 3.0 PHY 参考时钟线上加了串联电阻吸收反射问题才稳定下来。排查 USB 枚举耗时最长的一定要推荐工具usbmon加 Wireshark 抓包。内核开CONFIG_USB_MON在 host 端用modprobe usbmon后抓包看 USB 控制传输的返回状态能把问题定位到“设备没有响应”还是“host 没有下发”比盲改设备树快得多。3.2 OTG 和 Device/Gadget 模式切换RK3576 的 USB OTG 口支持 device 模式和 host 模式二者通过 dr_mode 属性或硬件角色切换引脚控制。我碰到的问题是在系统起来后切到 gadget 模式udc注册正常但插入开发机后主机没有任何反应。排查后确认是 OTG 角色控制引脚的电平不对RK3576 的 USB DT 节点里默认用了usb-role-switch和相关 GPIO 做角色识别但硬件上 GPIO 悬空导致系统始终认为自己处于 host 模式。解决方式是直接改设备树在 USB OTG 节点的控制器下把dr_mode强制设为peripheral如果还需要切换则在 GPIO 上配置正确的上拉或下拉。这里有一个非常实用的检查方法cat /sys/class/udc/*/role或者/sys/kernel/debug/usb/...可以立刻看到当前 phy 状态。别一上来就重编译内核先看系统识别到 UDC 设备没有。3.3 USB Hub 供电带来的奇怪复位外设一多USB Hub 是少不了的但这个反而是真的容易进“坑”。我的板上通过一个四口 USB 2.0 Hub 接了触摸屏、加密狗和两个串口转 USB 模块。当时发现只要同时插上三四个外设Hub 上的某个口就疯狂掉线重连甚至整个 USB 子系统崩溃。初步怀疑是 USB hub 芯片的问题换了好几个品牌都一样。后来量了电压才发现Hub 芯片的 5V 供电电压和实际负载的压降太大了插满设备时 5V 掉到 4.5V 以下很多 USB 设备就直接复位了。RK3576 板子的 USB 电源设计不能只靠 SoC 的 VBUS 引脚外设多的情况下最好单独做一个 5V/3A 以上的 DC-DC用 load switch 或使能脚控制同时 USB 端口要有足够容值的输入电容。这件事给我的教训是USB 外设供电的裕量远比想象重要宁可多留电也不能指望 Hub 自己撑住。3.4 USB 驱动加载顺序和设备编号随机我调试过程中还碰到一个特别影响体验的问题就是系统重启后 USB 串口设备/dev/ttyUSB0、ttyACM0的编号会变。串口工具通常写死/dev/ttyUSB0一旦内核枚举顺序变化程序就找不到设备。最省事的方案是用 udev 规则通过设备 ID 和物理端口路径创建稳定的符号链接比如/dev/device_camera - ttyUSB2。我在/etc/udev/rules.d/下写了一个基于KERNELS匹配的规则这样即使多个 USB 串口模块反复插拔端口路径也是固定的。这种方式强烈推荐比在应用层到处去搜索/dev/ttyUSB*可靠得多。4. 显示链路点亮屏幕就是过五关斩六将4.1 MIPI DSI上电时序和初始化序列缺一不可RK3576 的显示接口很丰富官方甚至支持多屏异显但工业项目通常只要单屏 MIPI DSI。我用的屏是 7 寸 1024x600 的 MIPI 屏第一版设备树照着别的平台改结果开机后屏幕背光亮但无画面。这个现象很有迷惑性背光亮说明 LCD 供电正常无画面往往是 DSI 时钟或初始化指令不对。看内核日志会发现dw-mipi-dsi-rk报了不少failed to get clock的提示。我把设备树里的assigned-clock-rates调整到 panel 要求的 HBP、HFP 值计算了一下 DSI clock最终确定是像素时钟偏低造成刷新率不对。后来我把 panel 驱动的initialized序列逐条放在dsi下面的panel节点里并通过panel-timing明确hactive/vactive等参数终于点亮了。这里提醒一下RK3576 的 DSI 支持 video mode 和 command mode你的 panel 是哪一种决定video-mode参数怎么配。不要照抄 EVB 的屏直接改型号。4.2 LVDS 屏和 VESA/JEIDA 映射问题另外一边因为项目需要宽温屏我做了一个 LVDS 的备选方案。RK3576 上有一个 LVDS 控制器但坑在数据映射屏接口支持 VESA 和 JEIDA 两种映射模式如果不匹配画面会明显出现颜色错乱或者雪花点甚至屏幕完全没有画面。我当时特意对比了两个品牌的同规格 LVDS 屏发现一个用的是 VESA 格式另一个用的是 JEIDA 格式。RK3576 的 DI、DPHY 驱动可以通过 devicetree 配置>
返回列表