ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

RK3568/RK3588实时Linux构建EtherCAT主站与LinuxCNC运动控制实战指南

RK3568/RK3588实时Linux构建EtherCAT主站与LinuxCNC运动控制实战指南 1. 硬件选型与架构为什么RK3568/RK3588能扛EtherCAT主站把一块RK3588开发板从“能跑Ubuntu”变成“能控制伺服电机”中间隔着的不是装几个软件包而是一整条从内核实时性、EtherCAT总线主站到LinuxCNC运动控制的链路。这篇内容把我在这条路上踩过、排过、最后跑通的细节都摊开讲清楚重点覆盖IgH主站在RK3568/RK3588上的编译加载、EtherCAT从站扫描与PDO/DC配置、LinuxCNC的lcec组件接线和轴组态以及大量网上查不到的处理经验。适合正在用RK3568/RK3588做运动控制项目、想绕开开发板厂商私有方案、自己掌控主站代码的人参考。1.1 RK3568/RK3588的实时控制底子EtherCAT主站本质是一套“对以太网帧收发时序极其敏感”的软件栈它要求网卡能快速收发帧、系统能在一个确定的时间窗口内完成周期数据处理。RK3568是四核Cortex-A55RK3588是四核A76A55八核主频都在2GHz上下跑Linux LinuxCNC EtherCAT主站的算力完全够。更重要的是这两颗SoC都自带千兆GMAC多数开发板会引出两路或以上的物理网口这正好满足EtherCAT工程里的基本要求一路网口专给总线另一路留着SSH和上位机GUI。很多做运动控制的人一看到“ARM跑EtherCAT”就担心实时性不够这个顾虑一半对一半不对。EtherCAT的物理层本质是100M以太网部分扩展是千兆对网卡吞吐的要求并不高真正的难点在于操作系统的响应延迟。只要把内核切到PREEMPT_RT全抢占实时内核再把RT线程绑到固定CPU核上1ms周期是非常稳的500µs周期好好调也有得玩。RK3588相比RK3568多出四个A76大核跑LinuxCNC的轨迹规划、HAL线程、甚至在上位机看halscope波形都不会跟EtherCAT主站抢资源。我实际测试下来RK3588上用PREEMPT_RT内核跑LinuxCNClcec1ms周期下总线抖动基本能压在40µs以内配合CPU隔离后cyclictest最大延迟做到100µs级别。这个水平已经覆盖了大量三轴雕刻机、五轴联动、绕线机、点胶机的需求。你要是手里只有RK3568也可以做四核A55跑1ms周期没有压力只是一边跑LinuxCNC一边跑GUI会稍微紧张建议GUI放在另一台机器上。1.2 主站与运动控制跑在同一颗SoC上的可行性边界先说结论RK3568/RK3588适合做“主站运动控制”一体化控制器但不适合盲目追求极短周期。EtherCAT主站每周期要完成的事包括组织出站帧、收发处理、读取从站反馈、把数据更新到运动控制软件。LinuxCNC侧还要同时计算插补、PID、报警逻辑。这些任务在RK3588上大概占用一颗A55核心的40%-70%取决于轴数和PDO大小。所以剩余的核心完全够跑GUI和PLC逻辑。周期上我的经验是1ms很稳几乎不需要极端调优500µs需要做CPU隔离、关闭DVFS、把网卡中断绑到合适的核上250µs很吃力这已经不是PREEMPT_RT的舒适区真要上得考虑Xenomai或者换x86 Industrial PC。另一个边界在从站数量。8根轴在1ms周期下每从站只放4-6个PDO数据RK3588毫无压力16根轴以上就要考虑裁剪PDO内容、禁用不用的同步管理器否则数据量上来后主站CPU占用会明显上升。1.3 供电、网口和散热上的硬件注意点这块很多人前期不重视实际踩坑最多。EtherCAT调试阶段最怕“时好时坏”十有八九是硬件层面的问题。网口规划EtherCAT主站只占用一个网口另一路千兆网口必须留给SSH和上位机通信。如果你的板子只有一个网口赶紧加一个USB3.0转千兆网卡用于调试但EtherCAT主站本身不要跑在USB网卡上USB路径的延迟和驱动质量都不适合总线实时收发。隔离供电伺服驱动器的开关电源会产生大量纹波和地环路干扰。我给RK3588的板子和外设单独用了一套12V工业开关电源伺服主回路另走一路两地之间只通过总线网线共地总线建议使用带屏蔽层的工业网线。散热CPU不要满载运行八核满载后SoC温度会迅速过70°C触发降频会让RT线程延迟突然恶化。RH3588开发板至少加一个主动散热风扇把CPU温度控制在55°C以下再来谈实时性。2. 实时内核与CPU隔离EtherCAT抖动控制的“地基”2.1 在RK3568/RK3588上编译全抢占RT内核的坑IgH主站在Linux下要获得可靠实时性最省力的方案就是PREEMPT_RT内核。RK3568/RK3588的开发板厂商通常给的是通用Ubuntu/Debian镜像内核带的是CONFIG_PREEMPT动态抢占而不是CONFIG_PREEMPT_RT全抢占。所以第一步往往是重新编内核。我走的路径是拉取Rockchip官方5.10内核分支再打上对应版本的linux-rt补丁。这里有第一个大坑——Rockchip的vendor内核改动很多官方RT补丁经常打不干净会报conflict。不要硬打两个解决办法用Rockchip自己发布的RT内核分支有些BSP版本里带-rt后缀或者社区维护的RT版内核直接换主线Linux内核RK3568/RK3588在5.10之后的主线支持已经相当完整主线打上RT补丁后反而干净。如果你是从零移植Ubuntu根文件系统到RK3588网上搜“RK3588移植Ubuntu”的教程很多建议在rootfs阶段就把RT内核编好放进去省得后面来回刷机。另外烧写完官方Ubuntu镜像后第一件事是把根分区扩容否则编译内核装deb包时经常碰到磁盘写满的尴尬。内核配置里这几个选项必须确认CONFIG_PREEMPT_RTy这才是真正的全抢占CONFIG_HZ_1000y时钟频率1000HzEtherCAT周期才能按毫秒级对齐CONFIG_CPU_ISOLATIONy、CONFIG_NO_HZ_FULLy后面做核隔离要用CONFIG_RCU_NOCB_CPUy把RCU回调从隔离核上挪出去。编译好后可以用uname -a确认内核有PREEMPT_RT字样再用zcat /proc/config.gz | grep PREEMPT做二次确认。很多所谓“RT镜像”其实只是把内核编译配置里的PREEMPT打开不是真正的RT这一步别省。2.2 CPU隔离与中断绑核的具体做法编译好RT内核只是“地基有材料”真正决定抖动大小的是系统把RT线程和中断安排在哪颗核上。RK3588的CPU0-3是A76CPU4-7是A55我做运动控制时习惯把RT线程和设备中断全部赶到A55核上A76留给GUI、编译和LinuxCNC的轨迹规划。在内核启动参数里加isolcpus4-7 nohz_full4-7 rcu_nocbs4-7这样CPU4-7从内核调度器里被隔离出来普通进程不会落上去RT线程再手动绑核就能独占。注意nohz_full需要勾选CONFIG_NO_HZ_FULLrcu_nocbs需要CONFIG_RCU_NOCB_CPU少一个参数都不生效。绑核用taskset最简单。LinuxCNC的HAL线程实际上是一个RT线程我会在启动脚本里对linuxcnc的RT进程做taskset -c 4或者直接用halcmd里的线程CPU亲和设置。如果你的实时任务是IgH主站自带的周期性任务也要一并绑定。另外必须关掉irqbalance否则系统会不停迁移中断。EtherCAT所在网卡的GMAC中断我实测下来不绑到RT核上反而更稳——让中断走一个非隔离核RT线程按自己的周期去读取RTDM接口的数据比“中断直接打透RT核”更容易控制延迟峰值。当然这只是经验值不同内核版本、不同驱动有差异建议用cyclictest前后对比。2.3 用cyclictest验证RT效果别急着上EtherCAT很多人编好RT内核就直接装IgH、直接接伺服结果总线断、伺服报警最后绕一大圈才发现是内核实时性没过关。我现在的流程是内核敲定后先跑满一晚上cyclictest。sudo cyclictest -t 1 -p 99 -i 1000 -m -l 1000000重点看Max列。RK3588上做了CPU隔离后Max通常在100µs上下如果超过200µs先别碰EtherCAT回到底层排查。用stress-ng --cpu 4 --matrix 1024去压A76核再观察RT核延迟有没有被带飞。这一步能筛掉很多系统层面的隐藏问题比如DVFS切频导致的大延迟、中断风暴、GPU驱动的异常调用等。如果延迟波动明显且都出现在频率切换的瞬间把RT核的cpufreq设为performance模式sudo cpupower frequency-set -g performance -c 4-7RK3588用A55核做RT时DVFS影响小一些但A76核在跑重负载时频率波动还是会影响片上缓存和总线竞争提前锁频很必要。3. IgH主站源码编译与模块加载从“能ping通”到“能认站”3.1 版本与依赖选择IgH EtherCAT Master就是我们常说的IgH主站开源社区里最主流的EtherCAT主站实现。我做RK3588集成时用的版本是1.5.2配合linuxcnc-ethercatlcec组件。lcec是目前LinuxCNC接EtherCAT最常用的桥接组件它把IgH的实时接口映射成HAL引脚。编译前先把内核头文件装好。如果你已经按第二节编好了自定义RT内核就装对应的linux-headers。然后按下面的流程编译IgHcd ethercat ./configure --prefix/opt/etherlab --enable-rtdm --enable-eoe --disable-8139too make sudo make modules_install install sudo depmod -a--prefix/opt/etherlab是社区惯用路径所有工具、库、模块都归拢到这里后续lcec找头文件也方便。--enable-rtdm是给lcec用的这个选项会编译出实时字符设备接口LinuxCNC的RT线程通过它跟内核态主站交换过程数据。--enable-eoe是Ethernet over EtherCAT纯做运动控制可以不开但开了不碍事以后想通过总线扩展一个网口时会省事很多。3.2 网卡驱动模式为什么RK3588要选generic而非特制驱动IgH主站加载时会接管一块网卡。它内部对常见网卡如RTL8169、Intel I210等有专门的驱动加速通道但RK3588的GMAC不在这份名单里所以只能用IgH的通用模式generic来接管网卡。通用模式会走内核网络设备路径性能上不如专有驱动但在RT内核和CPU隔离到位的前提下跑1ms周期完全能满足500µs周期也能用。加载主站模块前先决定好哪块网卡交给EtherCAT。假设板子上eth0是SSH网口eth1准备给总线sudo modprobe ec_master main_deviceseth1 sudo modprobe ec_rtdm加载成功后检查内核日志确认主站已经认到网卡。注意从这一刻起eth1不再有IP地址也不再参与普通网络通信。如果系统装了NetworkManager它会试图周期性去抢这块网卡导致主站异常。提前把它设置为不托管nmcli device set eth1 managed no这一步非常关键我见过多次“主站加载后没过几分钟总线就断掉”的案例最后都是NetworkManager在背后作妖。3.3 第一次扫站从“超时”到“全绿”的排查思路模块加载OK后用IgH自带的命令行工具扫站sudo /opt/etherlab/sbin/ethercat master sudo /opt/etherlab/sbin/ethercat slaves第一次扫到从站列表的那一瞬间整个系统才算真正打通了一半。如果你的结果里什么都看不到按下面的顺序排查不要上来就怀疑IgH配置查dmesg | grep -i ethercat确认主站有没有报“No slave found”或者网卡链路通不通用ethtool eth1看网卡link状态。EtherCAT从站通电后网口灯会亮如果灯不亮先查网线和网口确认第一个从站接的是主站网口并且从站本身已经上电。EtherCAT从站一般都有两个网口一个IN一个OUT第一个从站必须用IN口接主站接反了是扫不到的换一根短一点的工业网线再试很多“扫不到站”就是线序、屏蔽层、水晶头接触不良的问题如果从站列表里少了一两个多半是中间某根从站级联线松了。每个从站两个网口的作用就是为了级联透传数据帧从主站发出经过每个从站的IN口处理后再从OUT口传给下一个从站任何一个环节断了整条链后面的站全部消失。还有个很容易被忽略的点EtherCAT从站一般需要两个网口来级联主站端只需要一个网口。经常有人问“从站需要几个网口”其实指的就是这种菊花链结构导致的IN/OUT双口需求主站没有这个问题。4. 从站扫描、PDO映射与DC同步总线上让伺服真的转起来4.1 从站拓扑与PDO选择扫通从站之后别急着发运动指令。第一步是搞清楚每个从站的厂商ID、产品码和PDO能力。用命令sudo /opt/etherlab/sbin/ethercat slaves -v sudo /opt/etherlab/sbin/ethercat pdos sudo /opt/etherlab/sbin/ethercat sdospdos会列出每个从站当前可用的过程数据对象sdos能查看和修改对象字典。伺服驱动器比如常见的汇川、台达、松下系列出厂默认PDO可能并不满足你的需求你需要通过对象字典把控制字、状态字、目标位置、实际位置、模式字等关键参数塞进PDO里。这个过程本质上是在配置SyncManager的PDO分配。对大多数支持CiA402协议的伺服驱动器下面这张表是基础中的基础数据项方向常见对象字典索引控制字 Controlword主站→从站0x6040状态字 Statusword从站→主站0x6041模式字 Modes of Operation主站→从站0x6060目标位置 Target Position主站→从站0x607A目标速度 Target Velocity主站→从站0x60FF实际位置 Position Actual Value从站→主站0x6064实际速度 Velocity Actual Value从站→主站0x606C跟随误差 Following Error从站→主站0x60F4实际配置时先把驱动器切到总线模式下的“自定义PDO”再把需要的对象加到RxPDO主站发给从站和TxPDO从站发回主站。汇川系的驱动器通常还要额外设置0x1C12、0x1C13的PDO分配改完重启从站状态机才会生效。4.2 DC时钟同步的配置过程DCDistributed Clocks是EtherCAT区别于普通以太网实时方案的核心。原理是主站和每个从站内部都有高精度时钟主站通过测量物理链路传播延迟把各从站时钟对齐到同一个参考时钟上再通过SYNC信号让所有从站在同一时刻进行采样/输出。做了DC同步之后多轴联动不会因为各驱动器采样时间点不一致而产生轮廓误差。在IgH主站里DC使能并不是一行命令搞定的事。编译时主站默认带DC支持实际运行中由应用层比如lcec通过主站接口配置周期和同步模式。你在HAL侧要做的是保证LinuxCNC的base-thread周期和EtherCAT总线周期一致然后让lcec在主站初始化时把DC参数下发给从站。具体到伺服驱动器还要注意驱动器手册里的“位置环/速度环/电流环同步源”必须选择EtherCAT DC同步而不是内部自由运行如果驱动器支持多个SyncManagerPDO要分配到与DC同步对应的SyncManager通道上如果电机低速时有明显顿挫、电流声异常先看DC有没有对齐。有一种快速验证DC是否生效的办法把驱动器的MON输出引脚用示波器看或者让RT线程的LCEc.read周期误差暴露到halscope里。正常状态下每周期实际读到的总线反馈时间差应该是稳定的如果出现周期性漂移说明DC配置没生效。4.3 周期参数、看门狗与实测验证总线联调时不要一上来就设1ms。我习惯先用2ms周期把伺服状态机从OP模式拉到Ready点动一下确认方向再逐步缩到1ms甚至500µs。原因很简单新系统最早暴露的问题通常不是周期太慢而是总线抖动导致驱动器看门狗超时。很多驱动器默认看门狗是几毫秒一旦总线周期抖动超过设定值驱动器就会报通信故障并切断使能。排查这种问题先把驱动器侧的看门狗超时窗口调大比如调到4ms到8ms确认总线和LinuxCNC逻辑没问题再回头把看门狗收紧到实际能接受的底线。驱动器看门狗的具体对象索引在每家的手册里不一样没有统一值但基本都是0x100D附近的超时时间对象或厂商私有对象。实测时我还会用ethercat slaves -v反复确认所有从站状态机都在OP状态。只要有一个从站掉到SAFE_OP甚至INIT整个运动控制就会异常。这种掉站问题多数由两个原因导致一个是总线抖动超过从站容忍度另一个是PDO映射错误导致状态机切换失败后者典型的表象是“我改了对象字典再一重启状态机就卡住”。这种时候先回到ethercat pdos核对映射不要急着怀疑网线。另外关于FMMU很多人问它是不是能做数据加密。FMMUFieldbus Memory Management Unit是EtherCAT从站内部的逻辑地址映射单元它只负责把主站寻址的逻辑区间映射到从站物理存储上本身不涉及任何加密。真正需要数据安全时靠的是应用层协议或Safety over EtherCAT这类上层机制。FMMU最需要关心的反而是“映射别配错”一旦逻辑地址映射错位位置反馈读回来就全是乱数。5. LinuxCNC侧集成lcec组件与轴组态实操5.1 为什么LinuxCNC EtherCAT绕不开lcecLinuxCNC本身不原生支持EtherCAT它跟总线之间的桥梁就是linuxcnc-ethercatlcec。lcec把IgH主站的RTDM接口封装成一组HAL组件让每个从站变成一组HAL引脚你在HAL里像读写普通I/O一样读写伺服的数据。这也是LinuxCNC能快速对接各种EtherCAT驱动器的主要原因。在RK3588上编译lcec前先把LinuxCNC源码准备好。ARM64架构的Ubuntu上很少有现成的LinuxCNC ARM软件包建议直接源码编译LinuxCNC的uspace版本PreemptRT模式编译选项里要选--with-realtimeuspace这一类的参数。等LinuxCNC本体装好再编译lceccd linuxcnc-ethercat make sudo make installlcec编译时依赖IgH的/opt/etherlab头文件如果你在IgH里加过自定义补丁编译lcec之前最好确认两者的版本是匹配的否则会出现“RTDM接口找不到”之类的链接错误这类问题非常隐蔽。在HAL文件里核心是加载两个lcec的主模块loadrt lcec_master loadrt lcec_slave addf lcec.read base-thread addf lcec.write base-threadloadrt lcec_master负责建立IgH主站的HAL入口loadrt lcec_slave负责解析从站配置addf把lcec的读写函数挂到LinuxCNC的base-thread周期里。从站的具体配置写在LinuxCNC配置目录下的lcec_conf文件里每行定义一个从站至少包含主站编号、从站在链路上的位置、厂商ID、产品码。位置写错或者ID写错启动时就会报找不到从站卡在“Master not running”这类错误上。5.2 HAL引脚接线与轴组态那些一开始容易搞错的地方lcec加载后每个从站数据就变成了类似lcec.0.slave.0.command、lcec.0.slave.0.position-fb的HAL引脚。对于一台伺服轴最小闭环至少需要三路信号指令输出、位置反馈、使能控制。我见过很多新手把axis.N.motor-pos-cmd直接接到lcec.0.slave.0.command然后期望电机按位置跟随。这个做法不是不行前提是驱动器工作在位置模式并且你在驱动器里已经把位置环参数调好了。如果驱动器只做了速度环你给command一个位置值驱动器根本不会动。更通用的做法是LinuxCNC做位置环驱动器做速度环。接法类似loadrt pid namespid.x addf pid.x servo-thread net x-cmd axis.0.motor-pos-cmd # 来自LinuxCNC位置规划 net x-fb axis.0.motor-pos-fb # 来自伺服编码器反馈 net x-pid pid.x.command net x-pid pid.x.feedback net x-out pid.x.output setp pid.x.Pgain 0.5 setp pid.x.Dgain 0.05 # 把PID输出送到总线的速度给定 net x-out lcec.0.slave.0.command # 把总线反馈送回位置环和LinuxCNC net x-fb lcec.0.slave.0.position-fb这样做的好处是位置环在LinuxCNC里可以用halscope实时观察和调参不必反复去写驱动器参数。坏处是如果你伺服带的是刹车、抱闸或需要位置绝对值的应用要额外处理使能顺序和原点标定。还需要特别注意单位换算。LCEc的position-fb通常是从驱动器读回的原始位置单位可能是编码器脉冲数或µm而LinuxCNC的axis.N.motor-pos-fb期望的是用户单位比如mm。这个换算可以用HAL的scale组件处理也可以在驱动器的电子齿轮比对象0x6091/0x6092里先把单位折算成mm。我更喜欢后者因为换算关系在驱动器侧统一管理HAL里不用每个轴都挂scope。5.3 halscope调PID与回零配置轴组态出来以后先用LinuxCNC的halscope看波形再上电使能。重点观察三条曲线pid.x.error跟随误差、lcec.0.slave.0.position-fb总线反馈、lcec.read的运行时长。调PID的先后顺序是先调P让轴能动且不自激再加I消除稳态误差最后加一点D压过冲。如果波形上看到高频噪声先别动PID检查是不是编码器反馈毛刺或总线周期抖动导致。回零配置在ini文件里[JOINT_0] TYPE LINEAR MAX_VELOCITY 50 MAX_ACCELERATION 200 MIN_LIMIT -100 MAX_LIMIT 100 HOME_SEARCH_VELOCITY -5 HOME_LATCH_VELOCITY -1 HOME_INDEX_ENABLE 0如果驱动器带绝对值编码器可以跳过回零搜索直接用驱动器保存的原点。如果没有绝对值编码器就通过HAL把回零开关接到lcec.0.slave.0的数字输入引脚上再在LinuxCNC里配置HOME_SWITCH。注意回零方向先确认搜索方向对应实际机械方向否则碰到硬限位会触发报警。6. 高频故障排错实录与验收检查单6.1 “扫不到从站”的完整排查链路这个问题的排查链路我每次写文档都会给到现场同事因为电气工程师和软件工程师看到的现象一样但定位路径完全不同确认主站有没有拿到网卡dmesg | grep -i ethercat里如果压根没有主站初始化日志说明ec_master模块没加载成功回头检查内核模块参数和网卡名称。确认网卡链路ethtool eth1看Speed和Link detected。如果link down直接从网线、网口、从站供电查起。确认第一个从站第一个从站的IN口必须接主站OUT口接下一个从站。很多初装现场会把IN/OUT接反导致整链不通。确认从站供电EtherCAT从站在大部分方案里是外部独立供电不是总线供电。从站没上电时主站扫到链路是通的但没有任何站响应。确认硬盘/日志无异常如果扫描过程卡死多半是RT线程被系统调度打断检查cyclictest数据和CPU隔离配置。6.2 RT线程崩溃/看门狗超时的处理运动控制调试中最打击人的场景是轴动了几分钟驱动器突然报警“通信超时”或主站显示“lost link”。这种故障大概率不是硬件坏了而是某个瞬间总线延迟超过看门狗阈值。处理步骤查dmesg看有没有“RT task overrun”之类的实时超限日志用halscope抓lcec.read的执行周期观察有没有偶发的大脉冲。如果有去查那个时间点系统里还跑了什么高优先级任务比如GUI、网络服务、日志刷盘把rcu_nocbs和nohz_full的核隔离再核对一遍很多“偶发超时”是RCU回调落在RT核上导致的检查电源。伺服启动瞬间母线电流拉低可能导致主站板卡掉压或PHY芯片复位这种问题会表现为“启动伺服的一瞬间总线全断”。如果只是为了先排除总线问题可以把驱动器看门狗调大再跑一遍。如果看门狗调大后就再也不掉线说明驱动器和系统的时序余量不够要在周期、中断、电源三方面继续收敛而不是靠放宽看门狗糊弄过去。6.3 最后的运行性能清单我每次联调结束时都会按下面这张表逐项打勾所有项过了才敢把设备交给产线检查项参考结论cyclictest Max延迟隔离核≤150µs越低越好1ms总线周期实际抖动≤40µs所有从站状态机全部处于OP跟随误差稳定无发散趋势静止时接近0回零方向与软/硬限位已确认一致驱动器看门狗与总线周期匹配不是靠放宽掩盖问题网口分配EtherCAT网口不被NetworkManager托管电源隔离主站与伺服主回路不共地环路温度满载连续运行4小时CPU不超过65°C最后分享一个我个人的习惯EtherCAT联调台子上永远多备一根做好的短网线和一根标准网线。很多“疑难杂症”最后都败给了一根被压变形的网线或一个氧化严重的RJ45头。另一样值得常备的是一个可以夹在伺服MON输出上的示波器探头DC同步、位置环噪声、总线抖动最终都需要它在物理层给个准话。把这两样备好这个方案基本就能在RK3588上稳稳跑起来了。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进