ARTICLE DETAIL

资讯详情

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

RK3588实时内核与EtherCAT主站部署:PREEMPT_RT与IgH调优实践

RK3588实时内核与EtherCAT主站部署:PREEMPT_RT与IgH调优实践 在嵌入式计算和运动控制这个圈子里“RK3588跑EtherCAT主站”这两年问的人越来越多。原因不复杂越来越多的设备既要处理伺服轴运动又要跑视觉算法、数据上报、HMI逻辑纯单片机已经带不动这套组合拳。RK3588四颗A76大核算力足够双千兆网口也算标配碎屏价格又在可以接受的范围剩下唯一的槛就是Linux的实时性。EtherCAT要求主站以精确周期发送报文周期抖动通常要控制在几十微秒以内而普通Linux内核在调度、中断响应上的不确定性分分钟能到几百微秒。所以这篇文章我准备按一条完整的落地路径来写从PREEMPT_RT实时内核如何在RK3588上编译跑起来到IgH EtherCAT主站的板端部署再到那些真正影响抖动数据的调优细节。内容偏向我能直接复现的实操涉及到版本、参数、踩坑的环节我会单独标注清楚。1. 为什么是RK3588 PREEMPT_RT EtherCAT这套组合1.1 运动控制场景对主站硬件的真实需求EtherCAT主站本身不是一个计算密集型应用它做的事情说起来很枯燥每个周期典型1ms或500us把各从站的输出数据打包成一帧报文发出去再从返回帧里解析各从站的输入数据。轴数多的时候一个周期可能涉及几百个字节甚至上千字节的IO映像数据但这对CPU来说不算压力。真正的压力在于“准时”。伺服驱动器里的位置环周期一到EtherCAT报文就得出现在网线上晚个几十微秒可能就导致插补轨迹偏差、力矩波动严重时驱动器直接报警。主站CPU如果被其他任务抢占、中断响应慢、内存分配卡顿都会直接体现为报文的到达抖动。RK3588的优势在于它能把“跑实时通信”和“跑复杂应用”分开。四颗A76大核适合做高负载的逻辑和计算四颗A55小核可以用来处理一些低优先级任务。更重要的是它周边接口全千兆以太网、PCIe、USB3都能接扩展空间很大。实际部署时我把EtherCAT实时任务绑在A76大核上把视觉算法和数据库上报放在另外的核上这种隔离思路在它身上实现得很干净。1.2 PREEMPT_RT补丁解决的是调度延迟问题普通Linux内核为了保证文件系统、内存管理等临界区的数据一致性很多地方不允许被打断。结果就是用户态实时任务可能在任意时刻被内核挡住只能等内核把手里的事干完才轮到它跑。这个等待时间不可控最坏情况下能达到毫秒级对EtherCAT这种要求稳定的周期来说完全不可接受。PREEMPT_RT补丁做的事情就是把内核里绝大多数临界区改成可抢占的同时把中断处理线程化、把自旋锁换成优先级继承的互斥锁。打完补丁之后内核本身变成一个高优先级可抢占的任务任何用户态线程只要优先级够高都能在内核还没处理完某些操作时抢占进来。实测下来调度延迟能从普通内核的数百微秒压到几十微秒以内配合核隔离能进一步到个位数微秒。这里要强调一个容易被误解的点PREEMPT_RT解决了“Linux调度延迟不可控”的问题但解决不了“应用自己写得很烂”的问题。如果应用层在实时周期里做文件写入、malloc、printf照样产生抖动。所以实时内核只是基础整个链路的代码质量和任务设计同等重要。1.3 开源主站IgH在PREEMPT_RT方案中的生态位置EtherCAT主站有商业方案也有开源方案。商业方案如TwinCAT、Acontis功能完整、技术支持到位但授权费用不低。开源领域最具代表性的是IgH EtherCAT Master它既有内核态的主站模块也提供一套完整的用户态工具链适配普通千兆网卡就能工作不需要专门的实时网卡硬件。IgH和PREEMPT_RT是天然的搭档。IgH主站模块本身运行在内核态报文发送可在软中断或高优先级内核线程中完成周期任务可以走用户态并配合SCHED_FIFO调度。这种模式下实测周期抖动一般能控制在单周期时间的5%以内对于1ms周期来说就是50us以内满足绝大多数运动控制场景的要求。还有另一个开源主站SOEM很轻量适合裸机或嵌入式RTOS。但SOEM的用户态工具和文档不如IgH丰富且在Linux上的实时调度支持需要自己封装。如果目标是快速落地一个稳定可维护的Linux主站方案我建议直接选IgH。2. 实时内核编译部署从补丁合并到启动参数完整过程2.1 内核源码和RT补丁的版本匹配原则RT补丁不是随便打个压缩包就能用的它必须严格对应某个内核稳定版本。比如patch-5.10.110-rt66.patch只能打在linux-5.10.110原版内核上。RK3588芯片的官方BSP内核基于rockchip分支里面包含大量驱动和设备树改动直接打RT补丁几乎必然冲突。我在实践中选择的路线是以Rockchip官方内核源码仓库为底座找到和RT补丁版本最接近的Rockchip release分支然后尝试合并。简单说用5.10.y这个分支的某个版本配对应版本的RT补丁冲突通常会集中在少部分核心文件上手动解决后整体可用。有些开发者会选择直接从kernel.org的mainline拉一个纯上游内核再加载RK3588的设备树。现在上游对RK3588的支持已经比较友好基本外设都能识别。但这种方案的坑在于部分Rockchip私有外设比如某些编解码模块、特定IO扩展芯片在上游内核里没有完全支持得自己补驱动。我个人在量产项目里还是倾向用Rockchip BSP内核加RT补丁外设支持最全Rockchip的开发文档也以此为基础遇到问题容易排查。2.2 获取源码并合并RT补丁下面是Host端x86_64 Ubuntu上的一套可复现命令过程。先拉取Rockchip内核源码git clone -b linux-5.10.y-rockchip https://github.com/rockchip-linux/kernel.git cd kernel git checkout linux-5.10.110-rockchip接着从kernel.org拉取对应版本的RT补丁wget https://cdn.kernel.org/pub/linux/kernel/projects/rt/5.10/older/patch-5.10.110-rt66.patch.xz xz -d patch-5.10.110-rt66.patch.xz patch -p1 --dry-run patch-5.10.110-rt66.patch先用--dry-run看一眼会拒绝多少个文件。如果只有少量冲突可以去掉--dry-run直接合并再逐个手工解决。如果冲突文件很多多半是版本对不上建议换一个更接近的BSP tag。解决完冲突后建议立刻提交一次保留一份干净的“BSPRT补丁”基线方便后续反复调整配置。2.3 内核配置阶段必须打开的选项内核配置直接用Rockchip提供的默认配置做起点最省事。在源码根目录下make ARCHarm64 rockchip_linux_defconfig make ARCHarm64 menuconfig在menuconfig里找到内核特性选项打开实时抢占。5.10版本对应的是CONFIG_PREEMPT_RTy同时建议配以下几个方面CONFIG_HZ_1000y内核时钟节拍设为1000Hz提供更高的定时精度。CONFIG_NO_HZ_FULLy允许将隔离核设置为自适应无时钟模式减少空转时钟中断。CONFIG_CPU_FREQ_GOV_PERFORMANCEy确保后面可以用performance调频策略。CONFIG_RCU_NOCB_CPUy把RCU回调节点从隔离核上挪走。CONFIG_DEBUG_PREEMPTn关闭额外的抢占调试减小内核路径开销。这里有个容易被忽略的细节RT补丁合并成功后menuconfig里的Preemption Model应该出现“Fully Preemptible Kernel (Real-Time)”这个选项。如果只看到Voluntary Kernel Preemption之类说明RT补丁没有正确生效需要回头检查版本匹配。配置完成后交叉编译内核和设备树export ARCHarm64 export CROSS_COMPILEaarch64-linux-gnu- make Image dtbs -j$(nproc) make modules -j$(nproc)Rockchip的RK3588通常使用extlinux引导把编译好的Image打包进boot分区dtb按平台命名规则拷贝到对应目录modules安装到根文件系统。2.4 启动参数让实时任务拥有专用核心实时内核跑起来只是第一步真正要发挥性能启动参数必须配合隔离策略。我的rk3588启动参数里核心的一条是isolcpus2,3 nohz_full2,3 rcu_nocbs2,3含义是把CPU2和CPU3从普通Linux调度器中隔离出来。普通进程不会被分配到这两个核上实时任务和中断可以独占它们。nohz_full进一步让这两个核在空闲时不再接收周期性的时钟中断减少不必要的唤醒。rcu_nocbs把这两个核的RCU回调转移到其他核处理。配合频率管理cpufreq.off1或者如果不想完全关闭调频就确保后续用户态把governor切到performance。CPU频率跳变期间会引入额外的电源噪声和延迟实时场景下建议固定最高频率。启动后通过uname -a确认内核处于RT模式Linux rk3588 5.10.110-rt66 #1 SMP PREEMPT_RT看到PREEMPT_RT字样说明实时抢占已经打开。2.5 用cyclictest验证基线延迟在部署EtherCAT之前先跑一次cyclictest评估这块板子的调度延迟基线。安装rt-tests后执行cyclictest -t 5 -p 80 -i 1000 -d 0 -l 100000这个命令创建5个实时线程优先级80每个线程的间隔是1000us总共跑10万个周期。重点看最后的Max值。我手头这块RK3588在隔离核、固定最高频率、关闭watchdog的情况下Max通常稳定在5~17us之间。如果在没隔离、默认调频模式下这个数字能飙到100us以上。基线延迟决定了后面EtherCAT周期的最小可行上限。如果cyclictest的Max已经超过50us先不要急着去调EtherCAT回头继续优化内核配置和启动参数不然后面怎么调都压不下去。3. IgH主站交叉编译与板端部署的完整流程3.1 IgH源码获取与版本选择IgH主站的代码仓库可以从GitHub上的镜像或EtherLab官网找到。我建议用稳定分支比如stable-1.5。1.5版本成熟网上资料和问答最多踩坑时能搜到大量现成经验。1.6版本对某些新内核支持更好但配置接口有变化如果你对IgH不熟建议还是从1.5开始。git clone https://gitlab.com/etherlab.org/ethercat.git cd ethercat git checkout stable-1.53.2 configure参数和内核模块编译IgH编译需要指定目标机器的内核源码目录。先把RK3588内核源码放到固定的工作目录确保已经跑过make modules_prepare生成必要的头文件和符号表。交叉编译时用如下configureexport ARCHarm64 export CROSS_COMPILEaarch64-linux-gnu- export KERNEL_DIR/path/to/linux-5.10.110-rt66 ./configure --hostaarch64-linux-gnu --prefix/opt/etherlab \ --disable-8139too --disable-e1000e --disable-e100 \ --enable-generic --enable-rtdm逐个解释参数的用意--hostaarch64-linux-gnu指示交叉编译目标架构。--prefix/opt/etherlab用户态工具会安装到这个目录方便整体拷贝到板端。--disable-8139too --disable-e1000e --disable-e100关闭IgH自带的网卡私房驱动。默认情况下IgH可以为某些常见网卡编译专属驱动但RK3588的GMAC网卡并不在支持列表内留着反而增加编译负担。--enable-generic开启ec_generic这是IgH通用的纯软件驱动基于内核标准netif接口收发EtherCAT帧可以覆盖绝大多数网卡。--enable-rtdm启用RTDM接口。尽管我们在PREEMPT_RT模式下不一定依赖RTDM但保留它可以在未来切换Xenomai时不重新编译。然后开始编译make -j$(nproc) make modules这里有一个常见的坑IGH通过KERNEL_DIR找到内核源码但交叉编译内核模块时configure会检查内核版本和当前模块符号。如果之前没有在目标内核源码上跑过make modules_prepare ARCHarm64 CROSS_COMPILEaarch64-linux-gnu-编译模块时可能报一堆找不到头文件的错误。这个prepare动作消耗时间不长但很容易被忽略。编译完成后make modules_install需要root权限并指定安装目录。更简便的做法是直接把编译产物拷贝到板端scp master/.libs/ec_master.ko 路径... scp devices/.libs/ec_generic.ko 路径到板端/lib/modules/5.10.110-rt66/用户态工具整体装到/opt/etherlab拷贝到板端后还需要把/opt/etherlab/sbin加入PATH或建立软链。3.3 主站模块加载顺序与配置文件板端需要先加载内核模块再启动用户态服务。模块加载顺序是ec_master在前ec_generic在后modprobe ec_master modprobe ec_generic加载完成后IgH会在/sys/class/ethercat下创建主站节点用ethercat工具可以查看状态/opt/etherlab/sbin/ethercat master配置文件位于/etc/ethercat.conf核心内容MASTER0_DEVICEeth0 DEVICE_MODULESgeneric注意eth0必须对应你实际连接从站的那个网口。如果你的板子有两个网口一个用于管理网络SSH、NFS另一个用于EtherCAT一定要在配置里指定对的那一个否则IgH默认会使用第一个可用的网卡导致正常网络口被EtherCAT占用管理网络直接断掉。3.4 从站扫描的首次验证接入一个真实从站设备比如倍福的EK1100耦合器或一台伺服驱动器后先用工具扫描总线拓扑/opt/etherlab/sbin/ethercat slaves正常输出会列出从站的厂商ID、产品码和站地址。如果这条命令返回超时或看不到从站先检查网卡型号和PHY连接状态。不要急着怀疑软件问题EtherCAT对物理层质量很敏感网线过长、接触不良、PHY芯片自协商异常都会导致扫描失败。扫描通过后可以看一下主站的周期设置是否生效用/opt/etherlab/sbin/ethercat master输出里能看到主站当前的状态OPERATIONAL、PRE_OP等以及配置的周期时间。4. 实时调优的关键参数核隔离、中断绑核和调度策略的配合4.1 网络中断必须和实时任务绑到同一颗核很多人以为有了isolcpus把核隔离出来就万事大吉实际上忽略了中断绑核这一步。EtherCAT报文从网卡到达后网卡会产生中断中断默认可能落在CPU0或任意核上。如果中断处理核和实时应用所在的核不是同一个那么实时应用要等中断处理器把数据写进内存、释放锁中间跨核通信的延迟和缓存一致性开销会成为抖动的主要来源。做法是把网卡中断也绑定到隔离核上。先查网卡中断号cat /proc/interrupts | grep eth0找到中断号后把smp_affinity设置为对应核。假设CPU2的位掩码是0x4echo 4 /proc/irq/中断号/smp_affinity这个设置重启后会丢失建议写进启动脚本。注意如果把中断和实时任务绑定到同一个核这个核的上下文切换会比较密集但换来的是报文处理路径全程本地化整体确定性更好。4.2 主站线程使用SCHED_FIFO和taskset绑定IgH在用户态提供了周期任务的调用接口实际应用中需要自己写一段循环来周期调用EtherCAT的发送接收函数。这个用户态线程必须设置成实时调度策略并绑定到隔离核。在C程序里可以这样设置#include sched.h #include pthread.h struct sched_param param; param.sched_priority 80; pthread_setschedparam(pthread_self(), SCHED_FIFO, param); cpu_set_t set; CPU_ZERO(set); CPU_SET(2, set); pthread_setaffinity_np(pthread_self(), sizeof(set), set);SCHED_FIFO配合优先级80意味着这个线程可以抢占系统中绝大多数内核线程和用户线程。要注意优先级不要设得太离谱否则网卡中断线程可能被你饿死反而导致报文接收超时。我调试时见过有人把实时任务的优先级调到99结果把处理报文的中断线程堵住整个EtherCAT通信直接卡死。具体数值需要实验但80左右通常是比较稳的选择。4.3 关闭CPU调频、watchdog和其他后台干扰CPU动态调频在省电场景下很有用但在实时场景里是隐藏的抖动源。频率切换涉及电压调整整个切换过程可能长达几十微秒而且期间CPU性能也在变化。最简单的方案是启动参数直接关闭调频cpufreq.off1如果不想彻底关闭可以在用户态把governor设置为performanceecho performance /sys/devices/system/cpu/cpufreq/policy0/scaling_governorRK3588的CPU是大小核架构A55和A76各自的调频策略独立存在需要分别设置。watchdog在系统异常时会触发硬重启正常情况不工作但它内部有独立的定时器中断也可能引入微小干扰。实时系统追求极致时通常建议关闭echo 0 /proc/sys/kernel/watchdog echo 0 /proc/sys/kernel/nmi_watchdog还有一类后台任务容易被忽略系统日志rsyslog/journald、网络管理服务NetworkManager、容器运行时dockerd。它们可能在任何时刻唤醒并占用CPU。最稳妥的做法是让这些服务不占用隔离核并在系统上电后尽量处于静默状态。必要时可以在cpuset里把系统服务限制到非隔离核上运行。4.4 内存锁定与避免实时路径上的缺页异常用户态实时线程如果代码或数据不在内存里访问时就会触发page fault这个过程的耗时完全不可控对实时性来说是致命的。解决方法是把实时线程的内存钉在RAM里#include sys/mman.h mlockall(MCL_CURRENT | MCL_FUTURE);调用mlockall之后当前进程锁定的所有页面不会被交换出去后续新增的内存也自动锁定。在进程启动早期、在分配完所有实时需要的内存后调用一次之后实时循环里不要做动态内存分配。还要提前触发代码路径上的缺页。做法是在进入实时周期循环之前先完整跑一遍典型的发送接收逻辑包括初始化、分配、打开文件等这样所有涉及的代码页和数据页都被加载到内存实时循环运行期间就不会再触碰到缺页操作。4.5 一个典型的实时任务线程结构综合以上要点一个最小可用的实时循环大概长这样while (1) { // 等待下一个周期点 clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, next, NULL); // 写入输出数据 ec_master_sync_io(master); // 处理从站输入数据 ec_in_processdata(master); ec_out_processdata(master); // 计算下一个周期时间 timespec_add_us(next, cycle_time_us); }周期基准用CLOCK_MONOTONIC的绝对时间作为锚点每次都在固定的绝对时刻唤醒而不是简单usleep固定值。usleep方式会累积误差长时间运行后周期会偏离目标越来越远。绝对时间方式每个周期都校准到同一个时间轴长期稳定性好得多。5. 周期压力测试与抖动数据解读5.1 测试环境怎么搭最接近真实验证调优效果时不要只用一个简单从站就跑结论。真实场景里从站数量多、数据量大、总线负载高报文处理的时间也会不同。我搭测试环境的习惯是至少接入5台伺服驱动器如果条件限制没有真实的从站也可以用多个EtherCAT从站模拟器但模拟器的时序行为和真实硬件有差距最终验收还是要回归实际硬件。测试时同时开启一些干扰负载比如在非隔离核上跑一个编译任务或视频解码任务观察EtherCAT周期是否受到跨核干扰。这个测试很有价值因为实际生产环境中主站不可能独占整块板卡总有其他任务在运行。5.2 抖动数据怎么测才算数在实时循环里在每次周期唤醒时用clock_gettime记录当前时间和理论时间之间的差值累加出一组统计数据。一个完整的测试至少要跑10分钟以上只看前几秒钟的数据没有意义因为大部分系统在刚启动时资源充足抖动会偏低。最小抖动: 2us 平均抖动: 6us 最大抖动: 21us 超出10us的次数: 34 丢失周期次数: 0重点关注两个数字最大抖动和丢失周期次数。最大抖动决定了系统的最坏行为运动控制领域通常用最大抖动来评估是否满足伺服周期要求。丢失周期则意味着主站没有在周期内完成发送伺服很可能直接跟踪错误报警。一个合格的配置在100us周期内最大抖动最好控制在10us以内1ms周期控制在30us以内算是安全范围。5.3 长时间运行后的漂移与重连稳定性除了抖动还要观察长时间运行后分布时钟DC的漂移情况。EtherCAT的分布式时钟通过报文中的时间戳同步各从站时钟主站侧如果漂移过大伺服轴之间的同步精度会下降表现为多轴联动时的轮廓误差变大。IgH提供DC相关的配置选项可以在用户态初始化时设置同步模式。简单说启用DC同步后从站会根据主站发送的同步报文调整自己的本地时钟使每个周期都在同一时刻锁存输入输出。通过/opt/etherlab/sbin/ethercat dc命令可以查看DC状态。我遇到过一次比较诡异的情况DC漂移在最初两小时正常第四个小时开始逐渐增大最终导致从站失步。排查下来是因为板卡散热不良温度升高后PHY芯片的时钟抖动变大。所以长时间稳定性测试一定要跑够至少两小时有条件就过夜。5.4 通过EtherCAT调试接口定位异常IgH在内核debugfs里提供了丰富的诊断接口挂在/sys/kernel/debug/ec_master0/下。如果启用了debugfs并且模块编译时带有debug信息可以看到每个周期的收发统计、错误计数、从站状态变化记录。当抖动增大的时候先看/proc/interrupts确认网卡中断次数和分布再看debugfs下面的发送/接收计数是否有丢帧。如果丢帧频繁绝大多数原因出在物理层或网卡驱动而不是应用层代码。6. 网络拓扑与硬件层面的那些“隐形”实时性因素6.1 PHY芯片的时钟源直接影响抖动这是很多初次接触EtherCAT的人会忽略的一点。RK3588板载的GMAC需要外接PHY芯片PHY芯片必须有一个25MHz的参考时钟源。有的公板设计为了省一颗晶振用SoC输出的时钟信号驱动PHY如果SoC那边的时钟精度不够或者PDN设计有噪音EtherCAT帧的发送时钟就会跟着抖动。如果调试过程中发现周期抖动始终压不下去且软件调优已经做得比较彻底建议检查一下板子的PHY参考时钟是独立晶振还是SoC分频。独立晶振方案在实时性上更稳这也是为什么很多工业控制板会在网口附近放一颗高质量晶振而不是省掉它。6.2 交换机不适用于EtherCAT总线EtherCAT需要主站和从站构成一个环形或菊花链拓扑数据帧从主站发出经过每个从站时从站在硬件层直接抽取/插入数据并转发给下一个从站。普通交换机的转发逻辑会引入不可控的缓冲延迟直接破坏EtherCAT的实时性。所以网络上不要串联任何普通交换机线缆连接要严格遵循从站菊花链的顺序。此外拓扑长度和分支数量也有限制。虽然EtherCAT理论上支持几百个从站实际环形网络每个从站都会引入微小延迟站的响应时间会累加。如果总线周期时间要求小于500us接的从站数量又很多需要仔细校验每个从站的硬件转发延时指标。6.3 网卡驱动和环形缓冲区的配置RK3588的GMAC驱动在Linux下默认配置可能偏向吞吐量而非低延迟。可以调整网卡环形缓冲区大小和NAPINew API轮询的参数。在某些场景下把环形缓冲区调小可以让帧更及时地被处理而不是积压在大缓冲里但在高负载下缓冲太小又会丢帧具体数值需要根据实际测试来平衡。使用IgH的ec_generic驱动时它走的是内核标准网卡通道NAPI机制仍然存在。如果把处理EtherCAT帧的网卡中断绑定到隔离核并且在实时循环里主动调用接收处理那么即使NAPI稍微延迟也不会对最终周期产生太大影响。这部分没有统一的标准参数我通常先看ethtool -g eth0显示的当前ring buffer大小再用ethtool -G尝试不同值对比抖动数据。7. 实战排障清单连接不上、抖动异常、失步断线的排查路径7.1 主站扫描不到从站时的逐步定位这是最常遇到的问题。先查网络物理层ethtool eth0确认链接状态和速率是否为1000Mb/s。EtherCAT虽然不用IP协议但物理链路必须建立。如果链路显示down问题基本出在网线或PHY芯片配置上。如果链路up但是IgH扫描不到从站再用tcpdump抓包看是否能看到发送出去的EtherCAT帧tcpdump -i eth0 -e -n ethertype 0x88a4EtherCAT EtherType是0x88a4。如果抓不到发出的帧可能是主站没有进入运行状态如果发出了帧但没有收到回应大概率是从站侧的问题。按这个思路排除比瞎猜快得多。7.2 预留网口和EtherCAT网口冲突问题前面提到过IgH配置文件中MASTER0_DEVICE指定了绑定的网卡。如果RK3588有两个网口一个连接局域网做SSH和文件传输另一个连接EtherCAT两个网口的IP地址必须设置正确。很多人踩过的坑是EtherCAT网口本身不需要配置IP地址但不小心给配了IP导致系统路由表变得混乱管理网络的流量误入EtherCAT端口或者干脆让IgH绑错了网卡。建议EtherCAT网口在应用层不上IP或者把它的接口标记为手动不做DHCP。这样既避免路由混乱也减少系统对该网口的额外处理。7.3 周期运行中偶发超时或失步偶发性的失步是最头疼的。遇到这种情况先做一个最简单的事把/proc/interrupts里的网卡中断计数持续观察几分钟看是否有中断丢失或突然爆发。然后跑cyclictest看同时期的系统调度延迟有没有尖峰排除总线上有其他高优先级任务抢占。如果调度延迟正常再把怀疑放到PHY/物理层。我遇到过一次偶发超时结果是一根网线在机柜里被其他线缆挤压导致内部一对差分线的信号质量问题属于物理接线不规范引发的间歇性故障。这种问题软件调优无法根治只能靠重新布线、压好水晶头解决。7.4 在IgH和自定义应用之间做好状态机处理从站状态机INIT、PRE_OP、SAFE_OP、OPERATIONAL的管理看起来简单但处理不当会引起启动阶段反复重启的问题。IgH提供了从预运行到运行状态的切换接口应用在状态切换时要检查每个从站是否成功进入目标状态。我建议把状态切换过程做成带超时重试的步骤避免某个从站硬件没响应时整个主站卡死。实际调试中还发现某些从站要求主站周期性地发送特定控制字才能维持运行状态。如果应用在某个时刻长时间阻塞比如做了一次磁盘同步操作导致主站没来得及喂狗从站会自动掉到SAFE_OP状态。所以所有可能阻塞的操作都要从实时循环里挪出去放到一个非实时的辅助线程里处理。最后的经验沉淀整套方案从内核编译到EtherCAT主站跑通我自己走过多次弯路最深的一点体会是调优的顺序非常重要。先让内核的调度延迟数据好看再谈EtherCAT的周期稳定性先把物理层网络做扎实再动软件参数。很多人一上来就调IgH的任务周期结果发现再怎么调都突破不了内核调度延迟的瓶颈白费功夫。先跑cyclictest确认系统基线然后绑核、设置优先级、锁内存一步步来抖动数据会非常清晰地反映每一处优化的效果。另外别轻视持续测试的意义。实时抖动问题很多是偶发性的跑10分钟看不出问题不代表跑2小时没问题。我第一次交付前只做了短时间验证结果现场连续运行后出现周期性失步后来发现是散热导致的PHY时钟漂移。从那以后我的准则变成任何影响总线的改动都必须经过至少两小时的连续运行验证重点记录最大抖动和历史错误计数。这套方法论守住了很多次交付底线。
返回列表