最近着了powerlink的道,连续几晚十二点前没睡过觉。不得不说兴趣这东西劲太大了,让人睡不着。喜欢上研究POWERLINK,最新版的源码结构挺清晰的,移植并测试了嵌入式linux作为从站和电脑主站之间的通信,挺有趣的。接下来想尝试下在单片机上的移植,降低POWERLINK协议的使用门槛,让POWERLINK协议可以用的更广泛,算是件有意义的事。
以下分享下openPOWERLINK最新源码v2.7.2在单片机上的移植思路。
使用倒推法(由编译结果去推导需要依赖的代码文件),能够直观的看到平台差异性相关的文件。因此移植也很简单,照着以下指南来,肯定没问题。
openPOWERLINK最新源码地址:openPOWERLINK :: openPOWERLINK
powerlink不错的协议,但国人大都去卷ethercat了。我想powerlink这么好的协议真没啥难的,了解后会觉得比485总线还好用。之前就难资料太少,没人去研究推动和分享,我想趁我兴致正浓就多输出几篇分享给大家。
前提条件
openPOWERLINK源码要想成功运行在单片机上,需要一定的前提条件。最起码单片机板子上得有以太网功能吧。至于是否得有tcp/ip协议栈才能运行powerlink? 这个是非必要的,也就是说即便单片机板子上只有MCU+MAC+PHY芯片,没有移植lwip协议栈也是可以的。
如果是单片机mcu内核涵盖MAC链路层功能,则直接外接一颗PHY芯片即可。这需要单片机具备mac接口,一般像stm32F4系列以上的稍微高端点的单片机才具有mac功能。
媒体访问控制(MAC,Media Access Control),又称作介质访问控制,简称MAC,是局域网中数据链路层的下层部分,提供地址及媒体访问的控制方式,使得不同设备或网络上的节点可以在多点的网络上通信,而不会互相冲突,上述的特性在局域网中格外重要。早期网络发展时以MAC判别各个网络接口的位置,但后来互联网发展后,才有IP的制定与使用。若只是两台设备之间全双工的通信,因为两台设备可以同时发送及接收数据,不会冲突,因此不需要用到MAC协议。
媒体访问控制MAC子层负责解决与媒体接入有关的问题,在物理层的基础上进行无差错的通信。
MAC子层是网络与设备的接口,它从网络层接收数据帧,然后通过媒体访问规则和物理层将数据帧发送到物理链路上。它也从物理层接收数据帧,再送到网络层。总的来说,MAC有三大功能:
1.决定节点何时发送数据包。
2.将数据帧发送到物理层,然后发送到物理链路。
3.从物理层接收数据帧,然后送给网络层处理。
其中最重要的是第一点:决定节点何时发送数据包。对于每一种媒体访问控制技术,用来控制节点发送时机的规则叫做媒体访问规则。局域网上的节点不能想要发送数据就发送,节点只能在轮到它的时候才发送。
仅有STM32自带的MAC还不能做网络通信,还需要外接以太网PHY芯片才可以,如同RS485通信一样,仅有一个串口是不行的,还需要外接RS485的PHY芯片。
PHY(Port Physical Layer),可称之为端口物理层,是一个对OSI模型物理层的简称。现在常用于STM32的有DP83848,LAN8270,DM9161/9162等。这些PHY芯片都大同小异,基本寄存器都是一样的,只有扩展寄存和厂商专门设置的寄存器不同。如果用户将其中一个PHY驱动成功了,驱动另一个也是非常方便的。
如果低端点儿单片机没MAC功能呢?如何外接以太网芯片?办法也是有的,现在有的厂商提供集成的模块儿,自带MAC和PHY芯片的功能,对外通过SPI接口操作访问。如常用的芯片w5500芯片,就是一颗集成了MAC和PHY功能的芯片,通过SPI接口可以访问和使用。SPI接口几乎高低端的单片机都有的常见接口。W5500 芯片是一款集成全硬件 TCP/IP 协议栈的嵌入式以太网控制器,同时也是一颗工业级以太网控制芯片。是韩国WIZnet(微知纳特)发布全硬件TCP/IP协议栈以太网接口芯片。W5500 支持高速标准4线SPI接口与主机进行通信,该 SPI 速率理论上可以达到 80MHz。
综上所述,POWERLINK协议栈源码对单片机的要求并不高,一般的单片机都能满足,无论单片机mcu上是否具备MAC接口。协议栈源码也不是很大,不过当然mcu性能越高越好了。
移植指南
以下先给出一个编译过程日志,是POWERLINK协议栈嵌入式linux环境下的编译过程。通过整个编译过程可以看出有哪些文件源码参与了liboplkcn.a协议栈库的生成。(注,从站和主站用的是不同的协议栈库,从站的协议栈库叫liboplkcn.a,主站的是liboplkmn.a)
用倒推法,以结果为导向倒过来推导,就能很清晰的看明白,如果要移植到单片机上,有哪些接口是必须要实现的。
linux下的编译日志
以下为嵌入式linux平台上的编译日志:
-- CMAKE_SYSTEM_NAME is Linux
-- CMAKE_SYSTEM_PROCESSOR is arm
-- Adding CMAKE configuration options for Linux
-- Configuring oplkcn
-- Configuring done
-- Generating done
-- Build files have been written to: /root/test/powerlink/stack/build/arm-linux
root@hecs-287347:~/test/powerlink/stack/build/arm-linux# make
[ 1%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/api/generic.c.o
[ 2%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/api/processimage.c.o
[ 3%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/api/sdotest.c.o
[ 4%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/api/service.c.o
[ 6%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/obd/obdu.c.o
[ 7%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/obd/obdal.c.o
[ 8%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/dll/dllucal.c.o
[ 9%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/event/eventu.c.o
[ 10%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/nmt/nmtu.c.o
[ 12%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/nmt/nmtcnu.c.o
[ 13%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/nmt/nmtmnu.c.o
[ 14%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/nmt/identu.c.o
[ 15%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/nmt/statusu.c.o
[ 17%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/nmt/syncu.c.o
[ 18%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/pdo/pdou.c.o
[ 19%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/pdo/pdoucal.c.o
[ 20%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/pdo/pdoucal-triplebufshm.c.o
[ 21%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/sdo/sdotest-com.c.o
[ 23%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/sdo/sdotest-seq.c.o
[ 24%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/sdo/sdocom-dummy.c.o
[ 25%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/sdo/sdocom.c.o
[ 26%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/sdo/sdocom-std.c.o
[ 28%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/sdo/sdocomsrv.c.o
[ 29%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/sdo/sdocomclt.c.o
[ 30%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/sdo/sdoseq.c.o
[ 31%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/sdo/sdoasnd.c.o
[ 32%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/sdo/sdoudp.c.o
[ 34%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/timesync/timesyncu.c.o
[ 35%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/errhnd/errhndu.c.o
[ 36%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/ctrl/ctrlu.c.o
[ 37%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/sdo/sdoudp-linux.c.o
[ 39%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/ctrl/ctrlucal-direct.c.o
[ 40%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/dll/dllucal-circbuf.c.o
[ 41%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/errhnd/errhnducal-local.c.o
[ 42%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/event/eventucal-linux.c.o
[ 43%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/event/eventucalintf-circbuf.c.o
[ 45%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/pdo/pdoucalmem-local.c.o
[ 46%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/timesync/timesyncucal-local.c.o
[ 47%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/timer/timer-linuxuser.c.o
[ 48%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/dll/dllk.c.o
[ 50%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/dll/dllkfilter.c.o
[ 51%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/dll/dllkstatemachine.c.o
[ 52%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/dll/dllkevent.c.o
[ 53%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/dll/dllkframe.c.o
[ 54%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/dll/dllknode.c.o
[ 56%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/dll/dllkcal.c.o
[ 57%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/event/eventk.c.o
[ 58%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/nmt/nmtk.c.o
[ 59%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/pdo/pdok.c.o
[ 60%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/pdo/pdokcal.c.o
[ 62%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/pdo/pdokcal-triplebufshm.c.o
[ 63%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/pdo/pdoklut.c.o
[ 64%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/timesync/timesynck.c.o
[ 65%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/errhnd/errhndk.c.o
[ 67%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/errhnd/errhndkcal.c.o
[ 68%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/ctrl/ctrlk.c.o
[ 69%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/led/ledk.c.o
[ 70%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/led/ledktimer.c.o
[ 71%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/ctrl/ctrlkcal-direct.c.o
[ 73%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/dll/dllkcal-circbuf.c.o
[ 74%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/errhnd/errhndkcal-local.c.o
[ 75%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/event/eventkcal-linux.c.o
[ 76%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/event/eventkcalintf-circbuf.c.o
[ 78%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/pdo/pdokcalmem-local.c.o
[ 79%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/timesync/timesynckcal-local.c.o
[ 80%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/common/debugstr.c.o
[ 81%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/arch/linux/ftracedebug.c.o
[ 82%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/root/test/powerlink/contrib/trace/trace-printf.c.o
[ 84%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/arch/linux/target-linux.c.o
[ 85%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/arch/linux/target-mutex.c.o
[ 86%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/arch/linux/netif-linux.c.o
[ 87%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/obd/obdconf-fileio.c.o
[ 89%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/user/obd/obdconfcrc-generic.c.o
[ 90%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/common/circbuf/circbuffer.c.o
[ 91%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/common/circbuf/circbuf-posixshm.c.o
[ 92%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/common/memmap/memmap-null.c.o
[ 93%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/veth/veth-linuxuser.c.o
[ 95%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/timer/hrestimer-posix.c.o
[ 96%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/edrv/edrvcyclic.c.o
[ 97%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/kernel/edrv/edrv-rawsock_linux.c.o
[ 98%] Building C object proj/linux/liboplkcn/CMakeFiles/oplkcn.dir/__/__/__/src/common/ami/ami.c.o
[100%] Linking C static library liboplkcn.a
[100%] Built target oplkcn
编译日志分析
从日志过程看,源码也不多嘛,因此到此处应该增加对移植成功的信心。
接下来分析,跟linux平台相关的源码有哪些?
最重要的文件,src/kernel/edrv/edrv-rawsock_linux.c.o
这个是跟底层网络通信相关的核心驱动所在。
接下来的跟linux平台相关的还有:
src/kernel/veth/veth-linuxuser.c.o
src/arch/linux/target-linux.c.o
src/arch/linux/target-mutex.c.o
src/arch/linux/netif-linux.c.o
src/arch/linux/ftracedebug.c.o
src/kernel/event/eventkcal-linux.c.o
src/user/timer/timer-linuxuser.c.o
src/user/event/eventucal-linux.c.o
src/user/sdo/sdoudp-linux.c.o
就这些啦,看着像是很多?但是这里面其实有几个是不需要的,如sdoudp-linux.c,veth-linuxuser.c,
为何这两个文件不需要移植?先看下openPOWERLINK的代码架构框图:
图中标注的sdo接口部分似乎走了UDP协议,非得依赖tcp/ip协议栈?如果是使用了UDP那协议栈肯定是少不了了。
单片机上还得移植lwip协议栈?其实不用的,很简单。因为通过查看分析源码可以知道,虽然openPOWERLINK的sdo实现走了udp协议,但是这sdo发送接口是可配置的,它可以不使用udp发送,虽然看到的编译过程日志里有src/user/sdo/sdoudp-linux.c和src/user/sdo/sdoudp.c,但是CONFIG_INCLUDE_SDO_UDP这个配置并未启用。
sdoasnd.c,SDO over ASnd protocol,未配置CONFIG_INCLUDE_SDO_UDP,这样不走udp协议,则不需要非得有tcp/ip协议栈(当然单片机有tcp/ip协议栈也行,不影响) 。
src/kernel/veth/veth-linuxuser.c这个文件虽然编译日志里有它,但是实际也未用到。因为未启用CONFIG_INCLUDE_VETH这个宏定义。因此src/kernel/veth这个文件夹下的也可以略过。
最后剩下的涉及改动的文件,只有:
src/arch/linux/target-linux.c.o
src/arch/linux/target-mutex.c.o
src/arch/linux/netif-linux.c.o
src/arch/linux/ftracedebug.c.o
src/kernel/event/eventkcal-linux.c.o
src/user/timer/timer-linuxuser.c.o
src/user/event/eventucal-linux.c.o
再检查下看看还有没涉及到,发现还有个文件src/common/circbuf/circbuf-posixshm.c
它是个关于环形缓冲区的实现,这个好像依赖了posix规范。如果单片机环境中不具备的话,这个也好办,到src/common/circbuf下看看,有没有其他的实现,直接找一个拿来用就行啦。
其他的类似,如果不知道如何移植,可参照对应文件夹下的其他平台的实现照猫画虎,依葫芦画瓢,相信肯定都能搞定。
最后的最后,把以上涉及到的文件,单独摘出来到单片机里用吧,就这么简单。
移植完成。欢迎交流
其他资源
openPOWERLINK: openPOWERLINK