下载ethercat源码并且安装好之后,测试ethercat使用可以遵循以下步骤:
1.开启ethercat系统:执行这一步需要确保一点,那就是按照ethercat源码中的README指导将一些需要的文件复制以及创建软连接到/opt/init.d/ehtercat以及/opt/sysconfig/ethercat这两个文件,前者是系统启动文件,后者是系统配置文件,说起这个配置文件,其实就是一份变量定义文件,然后在系统启动脚本中执行了一下,定义两类变量,一个是主站MAC地址,一个是使用的模块驱动名称。分别是MASTER0_DEVICE和DEVICE_MODULES。MAC地址可以使用sudo ifconfig查到,至于module名称,这里使用generic进行测试(也就是通用模块);然后通过以下命令就可以开启ethercat系统。
sudo /etc/init.d/ethercat start
2.开启系统后,就要在应用层进行对主站模块的使用,本质上他是通过开启/dev/EtherCAT字符设备,而后基于ioctl方式调用内核主站模块各种功能的,其实主站在开启后自己本身还会创建
一个线程,空闲阶段和操作阶段(主站激活后)两种阶段中会使用线程执行不同的函数,原因主要就是两种阶段下,由于应用层会承担一部分代码工作(PDO交换、DC时钟同步),而此时的主站状态机代码相对来说不是那么重要,主要的子报文组装发送工作移动到应用层用户手中,因此采用了两个函数进行不同状态下的线程执行。
开启系统后,用户主要需要进行从站配置与PDO映射、域操作功能,然后就可以进行PDO交换了,当然,这个过程是基于主站状态机在后台完成了庞大的扫描工作后我们才得以进行这些操作的:
1.ec_master_t *ecrt_request_master(unsigned int master_index);
2.ec_domain_t *ecrt_master_create_domain(ec_master_t *master);
3.ec_slave_config_t *ecrt_master_slave_config(ec_master_t *master,uint16_t alias, uint16_t position, uint32_t vendor_id, uint32_t product_code);
4.int ecrt_slave_config_reg_pdo_entry(ec_slave_config_t *sc,uint16_t index, uint8_t subindex,ec_domain_t *domain,unsigned int *bit_position);
5.int ecrt_master_activate(ec_master_t *master);
6.uint8_t *ecrt_domain_data(ec_domain_t *domain);
7.void ecrt_domain_queue(ec_domain_t *domain);
8.void ecrt_master_send(ec_master_t *master);
以上,就是配置PDO基本需要使用到的函数,当然,主站程序运行在内核空间,应用层需要一种方式实现对内核调用。通过open主站创建的字符设备/dev/EtherCAT就是这一目的。
首先第一个函数ecrt_request_master(),负责打开字符设备文件,传入参数为使用主站索引(使用/etc/init.d/ethercat开启系统的时候可以一次性传入多个MAC地址从而开启多个主站,不同主站创建不同字符设备,如:/dev/EtherCAT0、/dev/EtherCAT1...),而这个索引就是用于开启对应的字符设备,从而使用不同的主站,使用open接口打开,然后返回文件描述符,该文件描述符用于ioctl调用对应主站功能。另外在申请到主站后就不在允许进行总线的重新扫描,固化了主站连接的从站链表,且设置从站状态当前申请状态为PREOP;
第二个函数ecrt_master_create_domain()创建域,domain与PDO映射有密切联系,之后在说到主站激活的位置细谈这部分;至于这个函数具体内容就是直接在内核空间中创建一块ec_domain_t空间并将该空间连接到主站domains链表尾部;
第三个函数ecrt_master_slave_config(),从站配置函数,说到从站配置函数,有个地方需要明确一下,那就是主站模块中的从站链表,他们之间的关系并不像我们想的那么紧密,首先,从站配置是应用层通过ecrt_master_slave_config()函数添加到主站的configs链表中的,而从站链表slaves则是通过ehtercat主站状态机通过扫描ethercat总线得到的,两者的共通之处就在于从站配置过程的alias、position、VID和PID,这些在主站扫描到的从站链表中都是有一份参数的,当应用层设置配置和主站扫描到的从站信息相匹配的时候,那就将从站与从站配置相联系(这时候会将主站扫描到的SII信息关于sync关联的PDO信息复制到从站配置中,也就是默认PDO配置);这样,就可以通过从站配置寻找到主站模块中从站配置信息,进而获取到从站信息。
第四个函数ecrt_slave_config_reg_pdo_entry(),该函数是从站配置PDO函数,首先需要注意一点,那就是在主站正式激活之前,所有配置PDO相关的其实并没有相对应的空间申请操作,一切都是进行的计算,计算PDO需要多大空间,计算domains的逻辑位置,计算FMMU的逻辑位置,计算PDO的逻辑位置,直到主站正式激活,主站会根据自身已经申请的域链表domains,获取所有域需要的空间大小,而后对每个域进行逻辑地址分配,每个域中再对每个FMMU进行逻辑地址分配。这样。言归正传,继续该函数研究,首先了解一下接口:
int ecrt_slave_config_reg_pdo_entry(ec_slave_config_t *sc,
uint16_t index, /* 对象字典索引 */
uint8_t subindex, /* 对象字典子索引 */
ec_domain_t *domain, /* 使用的域 */
unsigned int *bit_position)/* 一个Byte中的偏移量,当PDO映射逻辑地址不是完整的Byte时有用 */
首先,通过从站应用层配置索引可以获取到主站的从站配置链表中对应的从站配置,而后根据配置目标domain的索引获取到主站的domains链表对应的域,这样就可以实现应用层的从站配置和domain切换到主站对应的从站配置和domain,然后进行pdo映射操作。另外每次进行PDO映射的时候,并不是只对设置的一个对象进行处理,而是直接将整个sync关联的PDO都进行批次化处理:具体操作如下
1.找到PDO对象所在的sync同步管理器;
2.找到PDO对象在该同步管理器中的相对起始地址,如果该起始地址并不是整Byte数据,那么启用bit_position,如果没有,进行报警;
3.进行FMMU配置计算(FMMU管理映射是以一个sync关联的所有PDO进行映射的,因此只要配置的PDO对象的domain和sync是同一个,那就说明已经配置过对应sync,因此也就没必要新建FMMU去配置映射PDO),这里有几个空间块关系和逻辑地址需要明确一下,先说空间块,在主站没有激活之前,各个domians是无关的,domain内部由多个FMMU组成,每个FMMU配置映射是基于sync关联的PDO得到的(且经过字节对齐处理);然后就是domian->data_size,这个量只表明当前需要的空间大小,那么这个量也可以看作下一个需要配置的FMMU的起始逻辑地址,而对于PDO的逻辑地址,则可以通过在变量sync关联PDO过程进行获取,也就是第二步完成的操作;
所以,本质上来讲,PDO配置映射就是确定PDO的逻辑地址位置。
第五个函数ecrt_master_activate(),该函数为主站正式激活的函数,该函数完成以下功能:
1.主站注册的domains链表整体大小计算:经过PDO注册映射之后,对主站中关联的每个domains都是相互独立的,并且每个domains都只是一个计算得到的值,其实并没有需要的空间申请,因此在主站激活的时候会将全部domians需要的空间进行统一申请。具体申请到的PDO映射逻辑空间存放在字符设备打开文件的priv指针处,关于字符设备的file->priv在字符设备打开eccdev_open的时候进行指定。然后按照主站连接的domains链表顺序对每个domian起始地址进行设置:主要是domain的逻辑起始地址,domain的大小,以及domain中的FMMU的逻辑地址重新设置,最终,domain和FMMU的逻辑起始地址都是在主站全部domains环境下的逻辑起始地址。为了进行PDO映射,在主站激活过程中还对每个domain需要的子报文进行空间申请。在计算子报文需要个数的时候,各个domain计算各自需要的子报文需要,这样就可以满足不同domain的PDO交换周期是可以单独设置的;在domain计算自己需要的子报文个数的时候,计算是以FMMU为一个基本单位进行计算的,每个子报文可承载的数据大小为1486Byte,然后根据一个子报文中FMMU的输入输出情况设置子报文类型,也就是EC_DATAGRAM_LRD类型子报文,EC_DATAGRAM_LRR类型子报文以及EC_DATAGRAM_LRW类型子报文。然后将这些子报文添加到domain的datagram_pairs链表中。当然,整体过程中,domain映射空间和子报文使用的数据空间都是同一段空间。
2.完成主站的domains域空间处理,之后就停止主站的空闲阶段线程(等待空闲阶段线程退出);
3.开启主站的操作阶段线程,该线程和空闲阶段线程相比不同之处就在于将主站子报文队列组合发送移动到用户手中进行处理。
第六个函数ecrt_domain_data(),返回domain在逻辑空间的逻辑地址;
第七个函数ecrt_domain_queue(),就是将对应domain空间使用的子报文排列到主站子报文发送链表中;
第八个函数ecrt_master_send(),就是将主站的子报文发送链表的子报文进行发送(在发送过程中,默认的会将从站状态机子报文和主站状态机子报文进行排队发送);
以上,就是应用层执行PDO映射的基本原理。