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)反馈当前状态。
下面这张图把状态流转画清楚了,我建议你保存下来,调试时对照着看:
4.2 Init状态:从站上电后的第一口气
从站上电或复位后,ESC自动进入Init状态。这个阶段,从站只做一件事:等待主站通过EEPROM配置来初始化它。
在Init状态下,从站的行为非常有限:
- 不处理任何过程数据(PDO)——应用层完全休眠
- 不响应邮箱通信(Mailbox)——SDO、CoE等协议还没启动
- 只响应ESC寄存器访问——主站通过FMMU配置读写0x0000~0x0FFF区域
- DL信息寄存器可读——主站可以读取从站类型、版本等基本信息
4.3 Init阶段主站做了什么?
主站检测到从站在Init后,会做以下几件事。我按实际执行顺序列出来:
- 读取DL信息:从0x0000~0x0010区域读从站类型、版本、FMMU数量等
- 配置FMMU:写FMMU寄存器(0x0600~0x06FF),建立逻辑地址到物理地址的映射
- 配置SyncManager:写SM寄存器(0x0800~0x08FF),设置邮箱通道和过程数据通道
- 写站地址:通过配置数据(0x0010~0x0011)设置从站在总线中的位置
- 加载EEPROM配置:如果从站有外部EEPROM,主站可以写入或覆盖配置
这些配置都完成后,主站才会写AL Control寄存器,请求切换到Pre-Op。
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模块的滤波时间、编码器的分辨率等等。
4.6 Pre-Op阶段的应用层行为
从站固件在Pre-Op阶段应该做什么?我总结了一个清单:
- 初始化对象字典:把默认值加载到RAM中
- 配置硬件外设:比如初始化ADC、PWM、编码器接口
- 等待主站SDO配置:主站会逐个写对象字典,从站要正确响应
- 检查配置完整性:有些从站需要所有参数配完才能进入下一状态
- 准备PDO映射:虽然还没开始收发,但映射关系要准备好
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阶段遇到过不少问题。挑几个典型的说说:
原因通常是FMMU或SyncManager没配好。我建议你在主站代码里加个调试打印,把配置的FMMU和SM寄存器值读出来看看。有一次我发现FMMU的起始地址写错了,导致映射范围超出从站地址空间。
这多半是邮箱通道没配对。检查SM0(主站到从站)和SM1(从站到主站)的起始地址和长度。我记得有个项目,从站的邮箱缓冲区只有128字节,但主站配了256,结果数据写一半就丢了。
从站切换失败时,AL Status寄存器会置一个错误码。常见的有0x11(无效地址)、0x14(无效配置)、0x15(EEPROM错误)。查一下EtherCAT规范的表5-30,每个错误码都有明确含义。
4.9 小结
Init和Pre-Op是EtherCAT从站开发的第一个门槛。Init阶段主站做配置,从站被动等待;Pre-Op阶段邮箱通信启动,应用层开始初始化。这两个状态搞定了,后面的Safe-Op和OP就是水到渠成的事。