基于STM32构建EtherCAT主站(SOEM方案)2

本文介绍如何将EtherCAT主站软件SOEM移植到STM32平台,包括定时器驱动、以太网驱动等内容,并分享了移植过程中的注意事项及解决办法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2020年的12月初,我写了一篇《基于STM32构建EtherCAT主站(SOEM方案)1》博客,同时也上传了基于原子stm32f767开发板的源码(soem1.4.0版本,采用HAL库,控制伺服)。有兴趣的可以去我的博客目录找找。后续我会把整理好的源码上传到GitHub,如果发现了bug,或者我有讲错的地方,可以在评论区留言。欢迎指正。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
之前打算把移植过程都写到博客上的,后来由于有其它事要忙,就没继续写了。期间也有一些网友私信我,为什么不把博客写完。
好吧,在2022年元旦前后,我将把后续的几篇移植博客写完。未来,如果有时间的话,我还会分享一些《igh+xenomai》demo(一些有意思的小项目)。

我的梦想是写一个EtherCAT五轴数控系统(实现基础功能即可,在zynq、imx6ull、stm32mp157中选用一款作为数控系统的芯片跑linux或者其它实时系统,基于QT开发上位机),研究EtherCAT主站只是朝梦想方向前进的一小步,希望能在30岁之前把系统干出来。

哈哈,言归正传,继续来讲soem。王惠娇同志的硕士论文《基于嵌入式平台的EtherCAT主站实现研究》,把soem移植讲的很清楚了,有兴趣的可以读一下。如果你有移植lwip的经验,那么移植soem还是挺容易的。我个人移植过soem1.3.1和soem1.4.0,这两个版本基本没啥变动,因此移植过程也是一样的。soem项目中主要包含osal、oshw、soem三个文件夹。soem库采用了分层设计的思想,把操作系统层和硬件层抽象了出来,因此移植过程才会比较简单,只需修改osal和oshw文件夹中的文件即可。
在这里插入图片描述
移植的代码我是参考rtk子文件夹的(soem官方提供的移植平台代码),这是最贴近单片机开发的一个平台,lw_emac对应于stm32网卡驱动。
在这里插入图片描述

SOEM源码目录结构

soem:主站主体
osal:操作系统抽象层。提供了函数的抽象,如定时器和线程等。
oshw:硬件抽象层,网卡驱动。
test:应用示例代码

整个移植过程

1.stm32定时器驱动:tim2用于系统时基,为osal.c中的函数提供时间信息。tim5定时器中断用于应用层中的周期性程序。
2.以太网驱动,lan8720芯片初始化,以太网接收函数、以太网发送函数
3.nicdrv.c:把bfin_EMAC_send、bfin_EMAC_recv等函数替换成stm32的以太网收发函数。
4.oshw.c文件中修改一些大小端序的定义。
5.编译keil,采用–gnu编译(keil中可以设置),还会有一些其它的报错,主要是一些编译器导致的问题。根据报错修改即可。
6.参考soem/test/rtk/main.c文件,把其main函数移植到stm32中。
7.ethercat IO从站控制例程编写、ethercat伺服从站例程编写。
在这里插入图片描述
90%的移植工作集中在图中的红圈部分,大家根据自己板子的硬件,酌情修改即可。
下面的内容取自https://lipoyang.hatenablog.com/entry/2019/12/08/101951,一位日本网友的soem移植总结,大家在github上也能找到他的代码。
https://github.com/lipoyang/SOEM4Arduino
在这里插入图片描述

1.soem文件中的移植

(1.1)节省内存资源

最初的 SOEM 使用过多的 RAM 在单片微控制器上运行。因此,通过根据目标的内存容量减少以下常量来减少 RAM 使用量。
EC_MAXODLIST:CoE 对象字典的最大数量
EC_MAXOELIST:CoE 对象条目的最大数量
EC_MAXSLAVE:从站连接的最大数量
EC_MAXBUF:以太网帧缓冲区的数量

(1.2)时钟

原SOEM使用时间。但是,单片机系统可能没有实时时钟,或者即使有实时时钟,也可能精度不够。我决定用计时器来计算从微机启动开始经过的时间,并用它来代替。

(1.3)省略 LAN 端口冗余

原始 SOEM 支持两个 LAN 端口以进行冗余配置。但是,在只有一个 LAN 端口的系统的情况下,RAM 是浪费的。因此,删除以下与 LAN 口冗余配置相关的变量和函数。
ecx_redportt、ecx_init_redundant、ec_init_redundant

2.osal文件夹中的移植

(2.1)定时器和时钟

实现如下函数,根据微机对定时器进行抽象。
osal_usleep:在以 usec 为单位指定的时间内停止处理。
osal_timer_start:通过以 usec 为单位指定超时时间来启动计时器。
osal_timer_is_expired:返回计时器是否超时。
它还实现了以下抽象时钟的函数。但是,如(1.2)所述,这次将使用从微机启动开始的经过时间。
osal_current_time:获取当前时间。
osal_time_diff:返回两次之间的差值。

(2.2)线程

实现如下函数,根据微机对定时器进行抽象。但是,SOEM 本身并没有使用线程功能。如果在应用端不使用线程,即使不实现也没有问题。
osal_thread_create:创建线程
osal_thread_create_rt:创建实时线程

(2.3)调试输出

为调试输出实现 EC_PRINT 函数。在微机系统的情况下,通常输出到UART(串口)进行调试。 EC_PRINT 函数由宏定义,只有在定义了 EC_DEBUG 宏时才有效。 EC_PRINT 函数的实质是作为一个函数实现的,该函数采用与 printf 函数等效的可变长度参数。如果可以使用 printf 函数,请使用 #define EC_PRINT printf。

3.oshw的移植

(3.1)字节序

以太网协议是大端,但有些 CPU 是大端,有些是小端。因此,实现以下函数应该吸收字节顺序的差异。
oshw_htons:将 16 位整数从 CPU 字节顺序转换为大端。
oshw_ntohs:将 16 位整数从 big endian 转换为 CPU 字节顺序。

(3.2)搜索网络接口

实现以下功能以搜索可用的网络接口。但是,在大多数微机系统中,网络接口都是固定为已知的,如果应用端不需要这个功能,即使不实现也没有问题。
oshw_find_adapters:列出可用的网络接口。
oshw_free_adapters:释放用于枚举网络接口的内存。

(3.3)网卡设备驱动(这是最难的部分!)

实现以下抽象 NIC 设备的函数。
在这里插入图片描述
这是最难的一点,但要点总结如下。

(3.3.1)临界区

为了保护临界区,如果是操作系统环境,请使用互斥锁等。即使在没有 OS 的微型计算机系统中也使用中断,则需要中断禁用/启用处理。

(3.3.2)冗長構成の省略

如(1.3)所述,如果要省略LAN口的冗余配置,删除第二个LAN口相关的变量redport和redstate,处理使用这些变量的冗余配置也删除。

(3.3.3)句柄

在 Windows、Mac 和 Linux 等操作系统环境中,网络通信是基于套接字的,“RAW 套接字”也用于发送和接收原始以太网帧。处理这个的变量是 sockhandle。但是,除非需要在微机系统中处理套接字,否则不需要使用该变量。

(3.3.4)以太网控制器控制处理的实现

这是最重要的部分。根据需要移植的硬件实现以太网控制器的初始化处理、终止处理、帧发送处理、帧接收处理,并从需要的位置调用。
在这里插入图片描述

结语

soem移植大体就这些,说难不难,说简单也不简单。虽然我在2020年就已经把soem移植完了,也驱动了一些伺服,但是并没有在工业中应用,因此对移植后的可靠性也没有把握。自己也在工控行业干过,深知工业产品的高要求,以及细微的问题可能会带来巨大的损失,因此我的博客仅供学习和参考。
电机也不仅仅能转就完事了,我在nucleo f767平台移植过soem主站,板子上除了f767芯片,还有一颗stm32用于stlink功能。f767的时钟由另一颗stm32的PA8引脚提供(MCO功能),频率为8Mhz。测试过程中,发现伺服会周期性抖动。仔细研究后发现,是由于8Mhz的抖动有点大,比如实际是7.99999Mhz。最后只能通过参考时钟,动态调整主站周期,从而解决了问题。说白了就是DC同步,同步方法也是我自己琢磨的,也不敢保证对不对,也许只是碰巧解决了我单伺服的同步问题吧。
我是在研究生期间开始搞ethercat主站的,课题是基于igh+xenomai搞三轴数控。工作后,ethercat并不是我的工作内容,只是周末研究一下。开头说过,我的梦想是diy一套ethercat五轴数控系统。我真的很想有人送我一套工业ethercat主站源码,哈哈,可惜没有,因此只能自己折腾了。xenomai、igh、soem我都搞过,因为是单兵作战的缘故,许多坑要自己踩。经常一个问题要琢磨好久,没人指导,只能在百度、csdn、google、知网上疯狂找资料,反复读代码、调试。唉,搞起来真心累,好几次想放弃。
因为体验过那种被问题卡住时,寝食难安的状态。所以我把一些学习调试的过程写成博客,分享一下。我时间和能力有限,有些问题我也回答不出来。有时工作太累,或者遇到烦心事,没精力和心情回答。请见谅哈。

### 解决PyCharm无法加载Conda虚拟环境的方法 #### 配置设置 为了使 PyCharm 能够成功识别并使用 Conda 创建的虚拟环境,需确保 Anaconda 的路径已正确添加至系统的环境变量中[^1]。这一步骤至关重要,因为只有当 Python 解释器及其关联工具被加入 PATH 后,IDE 才能顺利找到它们。 对于 Windows 用户而言,在安装 Anaconda 时,默认情况下会询问是否将它添加到系统路径里;如果当时选择了否,则现在应该手动完成此操作。具体做法是在“高级系统设置”的“环境变量”选项内编辑 `Path` 变量,追加 Anaconda 安装目录下的 Scripts 文件夹位置。 另外,建议每次新建项目前都通过命令行先激活目标 conda env: ```bash conda activate myenvname ``` 接着再启动 IDE 进入工作区,这样有助于减少兼容性方面的问题发生概率。 #### 常见错误及修复方法 ##### 错误一:未发现任何解释器 症状表现为打开 PyCharm 新建工程向导页面找不到由 Conda 构建出来的 interpreter 列表项。此时应前往 Preferences/Settings -> Project:...->Python Interpreter 下方点击齿轮图标选择 Add...按钮来指定自定义的位置。按照提示浏览定位到对应版本 python.exe 的绝对地址即可解决问题。 ##### 错误二:权限不足导致 DLL 加载失败 有时即使指定了正确的解释器路径,仍可能遇到由于缺乏适当的操作系统级许可而引发的功能缺失现象。特别是涉及到调用某些特定类型的动态链接库 (Dynamic Link Library, .dll) 时尤为明显。因此拥有管理员身份执行相关动作显得尤为重要——无论是从终端还是图形界面触发创建新 venv 流程均如此处理能够有效规避此类隐患。 ##### 错误三:网络连接异常引起依赖下载超时 部分开发者反馈过因网速慢或者其他因素造成 pip install 操作中途断开进而影响整个项目的初始化进度条卡住的情况。对此可尝试调整镜像源加速获取速度或是离线模式预先准备好所需资源包后再继续后续步骤。 ---
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值