Ethercat和传统以太网的区别:
1:数据链路层不同。
2:Ethercat是实时性传输,传统以太网非实时。
Ethercat和Can总线的区别:
1:Ethercat完全兼容CanOpen协议。
2:Ethercat突破了Can总线中对SDO的包长 的限制。
3:Ethercat一次传输可以遍历多个节点。
Ethercat的优势:实时性与同步性;Ethercat可以保证数据传输的实时性,数据的传送仅仅收到两帧之间的安全时间限制。Ethercat所独有的同步性可以保证所有的节点同步触发,其抖动时间可以达到1us。
二、传输机制
ON The Fly(飞行中的数据帧),更形象的演示可以参考Ethercat的PPT中的介绍很好的解释了Ethercat的传输机制,每一帧数据包由主站发出后依次经过各个从站,在经过各个从站同时经行数据交换,几乎没有任何的延时即可遍历一个节点。这得益于Ethercat对数据链路层的改造。
注意:Ethercat是全双工的传输,所有的数据交互均发生在数据传输阶段,数据在返回主站时,不做任何操作,只是经过各个节点时进行单纯的转发操作。Ethercat的拓扑结构灵活,几乎支持任何一种的拓扑结构,数据帧的传输方向完全有拓扑结构来决定。
三、寻址方式(主站寻址从站)
顺序寻址:主站按照物理连接的先后顺序进行寻址,一般用在主机刚刚启动时。
设置寻址:主站按照设置给每个从站的地址进行寻址。
逻辑寻址:主站将每个从站的地址映射到一个虚拟的4G缓存区,进行寻址(这种寻址比较实用、方便)。逻辑寻址的管理有从站的FMMU进行管理,FMMU将本地内存映射到主机设置的4G内存中的一块区域中。主站可以通过逻辑地址方便的读取任一从站的内存。
四、运行模式
从站的运行模式可支持自由运行、DC同步模式、SM同步模式。
自由运行由从站自主控制运行周期,一般用于开机初始化过程中,主要完成一些初始化工作和状态机的切换。
DC同步模式受DC同步信号的控制,DC触发的周期由主站设置,DC的脉冲宽度可以再XML文件configdata中进行设置。DC模式可以保证从站设备节点的一致性,因为分布时钟是严格保持一致的。DC模式下可产生两个中断信号sync0、sync1,均可单独配置。DC中断可以用来传输周期性传输PDO数据或者周期性进行数据采集。
SM同步模式:SM中断etherca
tisr发生于有输入输出时间发生时,即当主站想从站发送数据或请求时会触发事件中断,可以保证及时响应主站的请求和命令。
五、数据传输方式
主站与从站进行数据交互的方式主要通过PDO和SDO,即过程数据和邮箱数据其概念与CANOpen中的概念相同。
PDO:过程数据用来传输周期性的数据,PDO由三个数据缓冲区组成,类似于一个FIFO,从站写入第一个缓冲区,主站从第三个缓冲区读走。注意第二个缓冲区不可操作。从站发送PDO和接受PDO各自采用两个独立的数据缓冲区。有同步管理器来控制缓冲区,每一个同步管理器只负责一种功能,例如同步管理器2负责发送PDO,同步管理器3负责接受PDO。
SDO:邮箱
通信用来发送非周期性的数据,邮箱通信只有一个数据缓冲区,通信方式采用握手的机制确保主从之间的数据交互不丢失,而PDO由于采用FIFO的机制,可能会出现新值覆盖旧值或旧值被多次读走的情况。SDO也由同步管理器来进行管理,发送和接受邮箱独立控制,例如同步管理器0控制发送邮箱,同步管理器1控制接受邮箱。
六、实时性的意义
在主从DC同步模式下,主站需要以非常精准的时间发送过程数据,如下图所示:
七、实时性的关键
如下图所示,影响实时性的关键因素是操作系统和网卡驱动,前者需要将过程数据准时送出,后者需要优化网卡驱动,即"准时出发,路上不能耽误"。
作系统的实时性体现在需要非常准时地调用EtherCAT主站协议栈的发送函数,例如SOEM的发送函数是ecx_send_processdata()
Etherlab的发送函数为ecrt_master_send()。
采用Linux系统时,需要打上实时补丁,如Xenomai、RTAI、OSADL等。
标准Linux下的网卡驱动是为通用的网络通信设计的,网络数据穿过TCP/IP协议栈是一个非常漫长的过程,其中包括各种安全性检查、路由、出入队列、分片和重组等等,这其中有很多的不确定性,所以在EtherCAT主站开发中需要优化网卡驱动,使EtherCAT数据
绕过TCP/IP协议栈。
八、移植网卡驱动
在Etherlab的说明文档中给出了改造标准网卡驱动的三个基本点,如下:
(1)禁用netif_*()
(2)禁用中断
(3)重复利用socket buffer
接下来以EtherLAB源码中移植好的网卡驱动RealTek RTL-8139为例进行说明。
1、禁用netif_*()
在网卡驱动程序中的接收函数rtl8139_rx()中,netif_receive_skb (skb)负责将数据包传递给TCP/IP协议栈,
将其改成由EtherCAT主站直接处理。
改造前:
- static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
- int budget)
- {
- ......
- netif_receive_skb (skb);//将数据包提交给TCP/IP协议栈处理
- ......
- }
- 改造后:
- static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
- int budget)
- {
- ......
- if (tp->ecdev) { //作为EtherCAT使用时直接交给EtherCAT协议栈处理,绕过TCP/IP协议栈
- ecdev_receive(tp->ecdev,
- &rx_ring[ring_offset + 4], pkt_size);
- dev->last_rx = jiffies;
- dev->stats.rx_bytes += pkt_size;
- dev->stats.rx_packets++;
- }
- else
- {
- ......
- netif_receive_skb (skb);
- ......
- }
- }
复制代码
2. 禁用中断
Linux标准网卡驱动中,采用中断方式收发网络数据包,较新的网卡驱动中采用NAPI(中断和轮询相结合),而EtherCAT通信中,EtherCAT主站发出过程数据包后,主站非常清楚数据包什么时候返回主站,因此不需要采用中断的方式,而由主站直接查询和处理返回的过程数据包。
改造前:
- static int rtl8139_open (struct net_device *dev)
- {
- ......
- retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev); //向内核注册中断
- ......
- }
- 改造后:
- static int rtl8139_open (struct net_device *dev)
- {
- ......
- if (!tp->ecdev) {
- retval = request_irq(dev->irq, rtl8139_interrupt, //作为普通网卡时才注册中断
- IRQF_SHARED, dev->name, dev);
- if (retval)
- return retval;
- }
- ......
- }
- void ec_poll(struct net_device *dev)
- {
- rtl8139_interrupt(0, dev);
- }
复制代码
- 函数调用关系为:ec_poll()->rtl8139_interrupt()->rtl8139_rx()->ecdev_receive();
复制代码
3. 重复利用Socket buffer
Linux标准网卡驱动中,将数据包发送后将释放数据包所占用的内存,或者放回预先分配的内存池中,
而EtherCAT通信中,只需重复使用其中的一两个缓存即可,这样可以节省为数据包分配和释放内存的时间。
改造前:
- static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb,
- struct net_device *dev)
- {
- ......
- dev_kfree_skb(skb);//释放Socket buffer所占内存或将其放回内存池
- ......
- }
- 改造后:
- static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb,
- struct net_device *dev)
- {
- ......
- if (!tp->ecdev) { //只有作为普通网卡时才释放Socket buffer
- dev_kfree_skb(skb);
- }
- ......
- }
复制代码