1.背景
2.EtherCAT主站软件方案
3.1 RT-Thread 下载
本次移植基于最新发布的release4.1.0, 这个可以到github下载,最近Gitee也更新了。移植EtherCAT之前,首先把Nuvoton的BSP跑起来。这个参考官方的文档就可以了。
3.2 Some移植
下载soem-1.4.0,将整个目录放在rt-thread项目里,下图是我的目录,供参考
在some-1.4.0及其子目录中需要手工编辑SConscript脚本,这儿就不展开了。后续我把源码打包发上来。
Some移植主要是三个文件 osal.c,oshw.c和nicdrv.c。
osal.c 主要是微秒及的延时和定时函数;
oshw.c 主要是网络端和本机端数据的大小端转换;
nicdrv.c 主要是网络数据收发。
Some已经给出了很多操作系统移植,我的移植是基于rtk,这个是嵌入式系统,和我们的开发环境最接近。
3.2.1 osal.c移植
主要内容是实现osal_usleep和osal_gettimeofday两个函数。
我开始思路是自定义一个定时器用于EtherCAT,当时用了Timer4。等实现差不多了,发现系统时钟用的是Timer5,很多地方功能重复。最终和系统共用Timer5,省了个Timer,代码也简化了不少。下面就是改动过的相关代码,osal_timer_init这个初始化函数要在启动EhterCAT功能之前调用。
1static rt_uint32_t us_ticks;
2void osal_timer_init(void)
3{
4 rt_uint32_t cmp = ETIMER_GetCompareData(5);
5 us_ticks = 1 * cmp / (1000000 / RT_TICK_PER_SECOND);
6 rt_kprintf("rt-thread hwtimer5 1us = %d ticks
", us_ticks);
7}
8int osal_usleep (uint32 usec)
9{
10 //udelay(usec);
11 /*ajustment for precision*/
12 //usec -= usec / 4080;
13 usec -= usec / 1500;
14 /*rt_hw_us_delay work for a delay less than 16us*/
15 do{
16 if(usec>=1000)
17 {
18 rt_hw_us_delay(1000);
19 usec -= 1000;
20 }else{
21 rt_hw_us_delay(usec);
22 usec = 0;
23 }
24 }while(usec>0);
25 return 0;
26}
27int osal_gettimeofday(struct timeval *tv, struct timezone *tz)
28{
29// return gettimeofday(tv, tz);
30 RT_ASSERT (tv != NULL);
31 rt_uint32_t timer_tick,rt_tick;
32 rt_base_t level = rt_hw_interrupt_disable();
33 timer_tick = ETIMER_GetCounter(5);
34 rt_tick = rt_tick_get();
35 rt_hw_interrupt_enable(level);
36 tv->tv_sec = rt_tick/1000;
37 tv->tv_usec = (rt_tick % 1000)*1000 + timer_tick / us_ticks;
38 return 0;
39}
3.2.2 oshw.c移植
不需做什么工作。
3.2.3 nicdrv.c移植
主要修改就是调用自己的网络发送和接收函数,我把它们命名为net_send和net_recv。这两个函数最好的实现是直接操作网卡(或者叫emac),我现在的实现参考了tcpdump的方法,在协议栈中加钩子(hook)实现,这样对原来系统影响最小,网口除了EtherCAT,还可以当正常的网口用。
ecx_setupnic函数中创建mutex(这个按照rt-thread格式改一下即可),安装网络钩子
ecx_closenic函数中删除mutex,卸载网络钩子。
3.2.4 net_hook.c实现
主要实现EtherCAT数据帧收发,中间加了个环形缓冲区用于接收。具体原理就是在网卡加个钩子函数,有数据来的时候先经过钩子函数,我们把EtherCAT数据帧截住,不传给原来的lwip协议栈;如果要发送数据,就直接调用发送函数,绕过lwip协议栈。这样也不影响lwip协议栈工作。
具体实现见附件。
3.2.5 some基本功能测试
采用官方的slave_info测试代码,测试主要分为时钟测试和soem EtherCAT协议栈基本功能测试。在终端中输入 soem_test + 回车即可。
我接了一个汇川IS620N驱动器,下面是输出的部分内容:
1Slave:1
2 Name:IS620N
3 Output size: 96bits
4 Input size: 224bits
5 State: 4
6 Delay: 0[ns]
7 Has DC: 1
8 DCParentport:0
9 Activeports:1.0.0.0
10 Configured address: 1001
11 Man: 00100000 ID: 000c0108 Rev: 00010001
12 SM0 A:1000 L: 128 F:00010026 Type:1
13 SM1 A:1400 L: 128 F:00010022 Type:2
14 SM2 A:1800 L: 12 F:00010064 Type:3
15 SM3 A:1c00 L: 28 F:00010020 Type:4
16 FMMU0 Ls:00000000 Ll: 12 Lsb:0 Leb:7 Ps:1800 Psb:0 Ty:02 Act:01
17 FMMU1 Ls:0000000c Ll: 28 Lsb:0 Leb:7 Ps:1c00 Psb:0 Ty:01 Act:01
18 FMMUfunc 0:1 1:2 2:0 3:0
19 MBX length wr: 128 rd: 128 MBX protocols : 04
20 CoE details: 0d FoE details: 00 EoE details: 00 SoE details: 00
21 Ebus current: 0[mA]
22 only LRD/LWR:0
4. 运动控制测试
基础工作做好以后,我们就能真正的控制电机运行了。在控制电机运行之前,还需要了解CIA402相关的规范,启动伺服需要按照规范要求,按顺序来。
程序主要流程如下,具体代码见附件。
a)初始化时钟 osal_timer_init
b)初始化网卡ec_init
c)等待进入INIT态
d)初始化驱动器(is620n)ec_config_init
e)DC配置
f)申请并等待进入Pre-OP态
g)配置过程数据TxPDO/RxPDO(自定义函数process_data_config)
h)配置FMMU ec_config_map
i)申请并等待进入Safe-OP态
j)设置CSP模式
k)发送和接收过程数据1次,触发SLAVE
l)申请并等待进入OP态
m)进入过程数据收发循环
在进入数据数据收发循环后,按次序发送控制字启动伺服(6040h发送6,7和15),然后就可以不断发送新的控制位置让电机转起来了!
5. 总结
版权声明:本文为RT-Threadwilliam hill官网 用户「lg28870983」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:
https://club.rt-thread.org/ask/article/160414965e80294e.html
———————End———————
你可以添加微信:rtthread2020 为好友,注明:公司+姓名,拉进RT-Thread官方微信交流群!
爱我就给我点在看
点击阅读原文
原文标题:NUC980 DIY项目大挑战 - EtherCAT实现
文章出处:【微信公众号:RTThread物联网操作系统】欢迎添加关注!文章转载请注明出处。
全部0条评论
快来发表一下你的评论吧 !