3. Sitara EtherCAT从站软件架构
在 Sitara AM335x/AM437x/AM57x 这类带 PRU-ICSS 的处理器上,EtherCAT 从站并不是“跑一个协议栈”那么简单,而是由三层协同构成:PRU-ICSS 内的 EtherCAT 从站控制器固件(ESC Firmware)、运行在 ARM 上的操作系统与驱动层、以及最上层的应用接口与过程数据接口(PDI)中断处理。理解这三层的分工与数据通路,是后续做从站移植、调试和性能优化的基础。
一、三层架构的分工
最底层是 PRU-ICSS EtherCAT 从站固件,TI 官方称为 PRU-ICSS EtherCAT Slave Firmware,它实现了 EtherCAT 从站控制器(ESC)的核心功能:EtherCAT 帧的收发、FMMU(Fieldbus Memory Management Unit)与 SM(SyncManager)通道管理、分布式时钟(DC)时间戳、EEPROM 读取与 SII 信息、以及过程数据接口(PDI)的读写。固件运行在两个 PRU 核上,一个负责 EtherCAT 数据链路(MII 收发与帧处理),另一个负责与 ARM 侧交互(PDI 接口、中断、寄存器访问)。
中间层是 ARM 侧的驱动与协议栈。在 SYS/BIOS 方案中,TI 提供 PRU-ICSS EtherCAT Slave Driver,配合 NDK 或裸机环境使用;在 Linux 方案中,则通过 UIO 或 remoteproc/rpmsg 暴露 PRU 寄存器与中断,再由 EtherCAT Master 协议栈(如 SOEM、IgH EtherCAT Master 的从站侧对应实现)或 TI 的 EtherCAT Slave Stack Code(SSC) 完成邮箱通信、CoE(CANopen over EtherCAT)对象字典、状态机(INIT→PREOP→SAFEOP→OP)管理。驱动层的核心职责是把 PRU 固件暴露的寄存器映射成可读写的内存区域,并把 PDI 中断转换为操作系统可处理的中断事件。
最上层是应用层接口。它通过 SSC 生成的 API(如 ECAT_Application、APPL_InputMapping、APPL_OutputMapping)把过程数据映射到用户变量,同时处理 CoE 对象字典的读写回调。应用层不直接触碰 PRU 寄存器,而是通过协议栈提供的接口完成数据交换。
二、PDI 中断:从站实时性的关键
PDI(Process Data Interface)中断是 PRU 固件通知 ARM 侧“过程数据已更新”或“需要发送新数据”的机制。在 AM335x 上,PRU 通过 PRU_ICSS 中断控制器向 ARM 的 INTC 发出中断请求,典型映射为 PRU_ICSS_EVTOUT0~7。以 SYS/BIOS 为例,配置流程如下:
// 1. 在 PRU 固件中使能 PDI 中断
// PRU1 写 PRU_ICSS_INTC 的 SRSR 寄存器
// 设置 PDI_ISR 位,触发 EVTOUT0
// 2. ARM 侧注册中断服务程序
Hwi_Params hwiParams;
Hwi_Params_init(&hwiParams);
hwiParams.arg = (UArg)&pdiEvent;
hwiParams.enableInt = TRUE;
Hwi_create(PRU_ICSS_EVTOUT0, pdiIsr, &hwiParams, NULL);
// 3. ISR 中读取过程数据
Void pdiIsr(UArg arg) {
// 从共享 RAM 读取输入数据
memcpy(inputBuffer, (void*)PRU_SHARED_RAM_IN, INPUT_SIZE);
// 处理输出数据
memcpy((void*)PRU_SHARED_RAM_OUT, outputBuffer, OUTPUT_SIZE);
// 清除中断标志
PRU_ICSS_INTC.SRSR = 0x01;
}
在 Linux 方案中,PDI 中断通常通过 UIO 设备暴露给用户空间,或由内核驱动注册 request_irq()。用户空间程序通过 read() 阻塞等待中断事件,再通过 mmap() 访问共享 RAM 完成数据交换。这种方式的实时性取决于内核调度延迟,通常需要配合 PREEMPT_RT 补丁或使用 SCHED_FIFO 实时线程。
三、应用层接口的实际使用
以 TI SSC 生成的代码为例,应用层需要实现三个关键回调:
APPL_InputMapping():将 ESC 收到的过程数据(如电机位置、传感器状态)复制到用户变量。APPL_OutputMapping():将用户变量(如控制指令、目标位置)写入 ESC 的输出缓冲区。APPL_Application():在状态机进入 OP 后周期调用,执行实际控制逻辑。
一个典型的映射示例如下:
// 输入映射:ESC 输入 → 用户变量
void APPL_InputMapping(UINT16* pData) {
// 假设输入过程数据为 4 字节位置 + 2 字节状态
gMotorPosition = *(INT32*)pData;
gSensorStatus = *(UINT16*)(pData + 2);
}
// 输出映射:用户变量 → ESC 输出
void APPL_OutputMapping(UINT16* pData) {
*(INT32*)pData = gTargetPosition;
*(UINT16*)(pData + 2) = gControlWord;
}
这里需要注意字节序与对齐:EtherCAT 过程数据按小端序传输,而 PRU 共享 RAM 的访问宽度为 32 位,映射时需确保指针类型与数据宽度匹配,否则会出现数据错位。
四、调试与验证要点
实际调试时,建议按以下顺序排查:
- 确认 PRU 固件加载成功:检查
/sys/class/remoteproc/remoteproc0/state是否为running,或 SYS/BIOS 下 PRU 是否已启动。 - 验证 PDI 中断是否触发:在 ISR 中翻转 GPIO 或用计数器统计中断次数,用示波器观察周期是否与 EtherCAT 周期一致(如 1ms)。
- 检查过程数据一致性:通过
ecat_master工具读取从站输入数据,与用户变量对比,确认映射无误。 - 观察状态机迁移:从 INIT→PREOP→SAFEOP→OP,每一步都应有对应的邮箱通信和 PDI 中断,若卡在 SAFEOP 通常是 DC 同步或看门狗配置问题。
总结来说,Sitara EtherCAT 从站软件架构的核心是“PRU 固件做实时链路、ARM 驱动做桥接、应用层做业务”的三层分工。PDI 中断是连接 PRU 与 ARM 的纽带,其配置与响应特性决定了从站的实时性能。理解这三层的接口与数据流,才能在后续的移植、优化和故障排查中快速定位问题。