4. NMT状态机详解(上):初始化与预运行

NMT状态机,说白了就是EtherCAT从站的“生命线”。每个从站芯片上电后,都得按这个状态机一步步走。我刚开始做EtherCAT开发时,总觉得状态切换就是写几个寄存器的事,结果调试时从站死活不进OP,折腾了两天才发现是初始化阶段的一个时序没卡对。

嗯,咱们今天先把前两个状态——Init(初始化)和Pre-Operational(预运行)——彻底讲透。这两个状态是基础,基础不牢,后面全是坑。

4.1 状态机全景:四个状态,三种切换

EtherCAT从站的状态机一共四个状态:Init、Pre-Operational、Safe-Operational、Operational。外加一个可选的Boot状态。主站通过写从站的AL Control寄存器(0x0120)来触发切换,从站通过AL Status寄存器(0x0130)反馈当前状态。

核心原则: 状态只能按顺序切换,不能跳级。比如从Init不能直接到OP,必须经过Pre-Op和Safe-Op。

下面这张图把状态流转画清楚了,我建议你保存下来,调试时对照着看:

EtherCAT NMT 状态机流转图 Init 初始化 Pre-Operational 预运行 Safe-Operational 安全运行 Operational 运行 (1) 初始化完成 (2) 配置完成 (3) 同步就绪 状态切换说明 • 必须按顺序切换 • 不能跳级 • 主站通过AL Control触发 • 从站通过AL Status反馈 • 任何状态都可回到Init • 错误时自动进入Init 回退/错误

4.2 Init状态:从站上电后的第一口气

从站上电或复位后,ESC自动进入Init状态。这个阶段,从站只做一件事:等待主站通过EEPROM配置来初始化它。

在Init状态下,从站的行为非常有限:

  • 不处理任何过程数据(PDO)——应用层完全休眠
  • 不响应邮箱通信(Mailbox)——SDO、CoE等协议还没启动
  • 只响应ESC寄存器访问——主站通过FMMU配置读写0x0000~0x0FFF区域
  • DL信息寄存器可读——主站可以读取从站类型、版本等基本信息
我的习惯: 调试新从站时,我第一步就是读AL Status寄存器(0x0130),确认它确实在Init状态。如果读回来是0x01以外的值,说明硬件复位或EEPROM加载有问题,先查电源和复位电路。

4.3 Init阶段主站做了什么?

主站检测到从站在Init后,会做以下几件事。我按实际执行顺序列出来:

  1. 读取DL信息:从0x0000~0x0010区域读从站类型、版本、FMMU数量等
  2. 配置FMMU:写FMMU寄存器(0x0600~0x06FF),建立逻辑地址到物理地址的映射
  3. 配置SyncManager:写SM寄存器(0x0800~0x08FF),设置邮箱通道和过程数据通道
  4. 写站地址:通过配置数据(0x0010~0x0011)设置从站在总线中的位置
  5. 加载EEPROM配置:如果从站有外部EEPROM,主站可以写入或覆盖配置

这些配置都完成后,主站才会写AL Control寄存器,请求切换到Pre-Op。

我曾经踩过的坑: 有一次我忘了配FMMU就直接发切换命令,从站死活不响应。查了半天才发现,从站虽然收到了AL Control写操作,但因为没有FMMU映射,邮箱通道根本不通。记住:Init阶段必须完成所有基础配置,否则后续状态切换会失败。

4.4 从Init到Pre-Op:状态切换的条件

主站写AL Control寄存器(0x0120)值为0x02,请求切换到Pre-Op。从站收到后,会做以下检查:

检查项 说明 失败后果
FMMU配置是否完整 至少一个FMMU通道已配置 AL Status置0x14(无效配置)
SyncManager配置是否完整 邮箱SM通道(SM0/SM1)已配置 AL Status置0x14
站地址是否有效 配置的地址在总线范围内 AL Status置0x11(无效地址)
EEPROM校验是否通过 如果EEPROM有校验,必须通过 AL Status置0x15(EEPROM错误)

检查通过后,从站将AL Status寄存器更新为0x02,表示已进入Pre-Op状态。同时,从站会触发一个状态改变中断(如果中断使能了),通知主站切换完成。

4.5 Pre-Operational状态:邮箱通信开始

进入Pre-Op后,从站的行为发生了质的变化:

  • 邮箱通信(Mailbox)启动:SDO、CoE、FoE等协议可以工作了
  • 过程数据(PDO)仍然禁止:应用层还不能收发实时数据
  • ESC寄存器继续可访问:主站可以读写所有寄存器区域
  • 应用层开始初始化:从站固件可以加载配置、初始化硬件外设

说白了,Pre-Op就是“配置阶段”。主站通过SDO读写对象字典,把从站的所有参数配好。比如伺服驱动的电流环参数、IO模块的滤波时间、编码器的分辨率等等。

关键点: Pre-Op状态下,从站必须能够响应SDO请求。如果SDO通信不通,后续的Safe-Op和OP想都别想。

4.6 Pre-Op阶段的应用层行为

从站固件在Pre-Op阶段应该做什么?我总结了一个清单:

  1. 初始化对象字典:把默认值加载到RAM中
  2. 配置硬件外设:比如初始化ADC、PWM、编码器接口
  3. 等待主站SDO配置:主站会逐个写对象字典,从站要正确响应
  4. 检查配置完整性:有些从站需要所有参数配完才能进入下一状态
  5. 准备PDO映射:虽然还没开始收发,但映射关系要准备好
我建议: 在Pre-Op阶段,从站固件可以打印调试信息或通过LED指示状态。我习惯让一个LED慢闪(1Hz),表示在Pre-Op。这样一眼就能看出从站卡在哪个阶段。

4.7 状态切换的ESC行为总结

我把Init和Pre-Op两个状态下,ESC的核心行为整理成了一张表。调试时对照着看,能省不少时间:

功能 Init状态 Pre-Op状态
ESC寄存器访问 全部可读写 全部可读写
邮箱通信 禁止 允许(SM0/SM1)
过程数据通信 禁止 禁止
FMMU映射 未生效 已生效(但无数据)
SyncManager 未配置 已配置
应用层 休眠 初始化中
AL Status值 0x01 0x02

4.8 常见问题与避坑指南

做EtherCAT开发这几年,我在Init和Pre-Op阶段遇到过不少问题。挑几个典型的说说:

问题1:从站卡在Init,不进Pre-Op
原因通常是FMMU或SyncManager没配好。我建议你在主站代码里加个调试打印,把配置的FMMU和SM寄存器值读出来看看。有一次我发现FMMU的起始地址写错了,导致映射范围超出从站地址空间。
问题2:进入Pre-Op后SDO通信超时
这多半是邮箱通道没配对。检查SM0(主站到从站)和SM1(从站到主站)的起始地址和长度。我记得有个项目,从站的邮箱缓冲区只有128字节,但主站配了256,结果数据写一半就丢了。
问题3:AL Status显示错误码
从站切换失败时,AL Status寄存器会置一个错误码。常见的有0x11(无效地址)、0x14(无效配置)、0x15(EEPROM错误)。查一下EtherCAT规范的表5-30,每个错误码都有明确含义。

4.9 小结

Init和Pre-Op是EtherCAT从站开发的第一个门槛。Init阶段主站做配置,从站被动等待;Pre-Op阶段邮箱通信启动,应用层开始初始化。这两个状态搞定了,后面的Safe-Op和OP就是水到渠成的事。