ethercatbase.c
Go to the documentation of this file.
00001 /*
00002  * Simple Open EtherCAT Master Library 
00003  *
00004  * File    : ethercatbase.c
00005  * Version : 1.3.0
00006  * Date    : 24-02-2013
00007  * Copyright (C) 2005-2013 Speciaal Machinefabriek Ketels v.o.f.
00008  * Copyright (C) 2005-2013 Arthur Ketels
00009  * Copyright (C) 2008-2009 TU/e Technische Universiteit Eindhoven 
00010  *
00011  * SOEM is free software; you can redistribute it and/or modify it under
00012  * the terms of the GNU General Public License version 2 as published by the Free
00013  * Software Foundation.
00014  *
00015  * SOEM is distributed in the hope that it will be useful, but WITHOUT ANY
00016  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00017  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00018  * for more details.
00019  *
00020  * As a special exception, if other files instantiate templates or use macros
00021  * or inline functions from this file, or you compile this file and link it
00022  * with other works to produce a work based on this file, this file does not
00023  * by itself cause the resulting work to be covered by the GNU General Public
00024  * License. However the source code for this file must still be made available
00025  * in accordance with section (3) of the GNU General Public License.
00026  *
00027  * This exception does not invalidate any other reasons why a work based on
00028  * this file might be covered by the GNU General Public License.
00029  *
00030  * The EtherCAT Technology, the trade name and logo “EtherCAT” are the intellectual
00031  * property of, and protected by Beckhoff Automation GmbH. You can use SOEM for
00032  * the sole purpose of creating, using and/or selling or otherwise distributing
00033  * an EtherCAT network master provided that an EtherCAT Master License is obtained
00034  * from Beckhoff Automation GmbH.
00035  *
00036  * In case you did not receive a copy of the EtherCAT Master License along with
00037  * SOEM write to Beckhoff Automation GmbH, Eiserstraße 5, D-33415 Verl, Germany
00038  * (www.beckhoff.com).
00039  */
00040 
00052 #include <stdio.h>
00053 #include <string.h>
00054 #include "ethercat_soem/oshw.h"
00055 #include "ethercat_soem/osal.h"
00056 #include "ethercat_soem/ethercattype.h"
00057 #include "ethercat_soem/ethercatbase.h"
00058 
00059 
00072 int ecx_setupdatagram(ecx_portt *port, void *frame, uint8 com, uint8 idx, uint16 ADP, uint16 ADO, uint16 length, void *data)
00073 {
00074    ec_comt *datagramP;
00075    uint8 *frameP;
00076 
00077    frameP = frame;
00078    /* Ethernet header is preset and fixed in frame buffers
00079       EtherCAT header needs to be added after that */
00080    datagramP = (ec_comt*)&frameP[ETH_HEADERSIZE];
00081    datagramP->elength = htoes(EC_ECATTYPE + EC_HEADERSIZE + length);
00082    datagramP->command = com;
00083    datagramP->index = idx; 
00084    datagramP->ADP = htoes(ADP);
00085    datagramP->ADO = htoes(ADO);
00086    datagramP->dlength = htoes(length); 
00087    if (length > 0)
00088    {
00089       memcpy(&frameP[ETH_HEADERSIZE + EC_HEADERSIZE], data, length);
00090    }
00091    /* set WKC to zero */
00092    frameP[ETH_HEADERSIZE + EC_HEADERSIZE + length] = 0x00;
00093    frameP[ETH_HEADERSIZE + EC_HEADERSIZE + length + 1] = 0x00;
00094    /* set size of frame in buffer array */
00095    port->txbuflength[idx] = ETH_HEADERSIZE + EC_HEADERSIZE + EC_WKCSIZE + length;
00096 
00097    return 0;
00098 }
00099 
00113 int ecx_adddatagram(ecx_portt *port, void *frame, uint8 com, uint8 idx, boolean more, uint16 ADP, uint16 ADO, uint16 length, void *data)
00114 {
00115    ec_comt *datagramP;
00116    uint8 *frameP;
00117    uint16 prevlength;
00118 
00119    frameP = frame;
00120    /* copy previous frame size */
00121    prevlength = port->txbuflength[idx]; 
00122    datagramP = (ec_comt*)&frameP[ETH_HEADERSIZE];
00123    /* add new datagram to ethernet frame size */
00124    datagramP->elength = htoes( etohs(datagramP->elength) + EC_HEADERSIZE + length );
00125    /* add "datagram follows" flag to previous subframe dlength */
00126    datagramP->dlength = htoes( etohs(datagramP->dlength) | EC_DATAGRAMFOLLOWS );
00127    /* set new EtherCAT header position */
00128    datagramP = (ec_comt*)&frameP[prevlength - EC_ELENGTHSIZE];
00129    datagramP->command = com;
00130    datagramP->index = idx; 
00131    datagramP->ADP = htoes(ADP);
00132    datagramP->ADO = htoes(ADO);
00133    if (more)
00134    {
00135       /* this is not the last datagram to add */
00136       datagramP->dlength = htoes(length | EC_DATAGRAMFOLLOWS); 
00137    }
00138    else
00139    {
00140       /* this is the last datagram in the frame */
00141       datagramP->dlength = htoes(length); 
00142    }
00143    if (length > 0)
00144    {
00145       memcpy(&frameP[prevlength + EC_HEADERSIZE - EC_ELENGTHSIZE], data, length);
00146    }   
00147    /* set WKC to zero */
00148    frameP[prevlength + EC_HEADERSIZE - EC_ELENGTHSIZE + length] = 0x00;
00149    frameP[prevlength + EC_HEADERSIZE - EC_ELENGTHSIZE + length + 1] = 0x00;
00150    /* set size of frame in buffer array */
00151    port->txbuflength[idx] = prevlength + EC_HEADERSIZE - EC_ELENGTHSIZE + EC_WKCSIZE + length;
00152 
00153    /* return offset to data in rx frame
00154       14 bytes smaller than tx frame due to stripping of ethernet header */
00155    return prevlength + EC_HEADERSIZE - EC_ELENGTHSIZE - ETH_HEADERSIZE;  
00156 }
00157 
00168 int ecx_BWR (ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00169 {
00170    uint8 idx;
00171    int wkc;
00172 
00173    /* get fresh index */
00174    idx = ecx_getindex (port);
00175    /* setup datagram */
00176    ecx_setupdatagram (port, &(port->txbuf[idx]), EC_CMD_BWR, idx, ADP, ADO, length, data);
00177    /* send data and wait for answer */
00178    wkc = ecx_srconfirm (port, idx, timeout);
00179    /* clear buffer status */
00180    ecx_setbufstat (port, idx, EC_BUF_EMPTY);
00181 
00182    return wkc;
00183 }   
00184 
00195 int ecx_BRD(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00196 {
00197    uint8 idx;
00198    int wkc;
00199 
00200    /* get fresh index */
00201    idx = ecx_getindex(port);
00202    /* setup datagram */
00203    ecx_setupdatagram(port, &(port->txbuf[idx]), EC_CMD_BRD, idx, ADP, ADO, length, data);
00204    /* send data and wait for answer */
00205    wkc = ecx_srconfirm (port, idx, timeout);
00206    if (wkc > 0)
00207    {
00208       /* copy datagram to data buffer */
00209       memcpy(data, &(port->rxbuf[idx][EC_HEADERSIZE]), length);
00210    }   
00211    /* clear buffer status */
00212    ecx_setbufstat(port, idx, EC_BUF_EMPTY);
00213 
00214    return wkc;
00215 }   
00216 
00227 int ecx_APRD(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00228 {
00229    int wkc;
00230    uint8 idx;
00231 
00232    idx = ecx_getindex(port);
00233    ecx_setupdatagram(port, &(port->txbuf[idx]), EC_CMD_APRD, idx, ADP, ADO, length, data);
00234    wkc = ecx_srconfirm(port, idx, timeout);
00235    if (wkc > 0)
00236    {
00237       memcpy(data, &(port->rxbuf[idx][EC_HEADERSIZE]), length);
00238    }
00239    ecx_setbufstat(port, idx, EC_BUF_EMPTY);
00240 
00241    return wkc;
00242 }
00243 
00255 int ecx_ARMW(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00256 {
00257    int wkc;
00258    uint8 idx;
00259 
00260    idx = ecx_getindex(port);
00261    ecx_setupdatagram(port, &(port->txbuf[idx]), EC_CMD_ARMW, idx, ADP, ADO, length, data);
00262    wkc = ecx_srconfirm(port, idx, timeout);
00263    if (wkc > 0)
00264    {
00265       memcpy(data, &(port->rxbuf[idx][EC_HEADERSIZE]), length);
00266    }
00267    ecx_setbufstat(port, idx, EC_BUF_EMPTY);
00268 
00269    return wkc;
00270 }
00271 
00283 int ecx_FRMW(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00284 {
00285    int wkc;
00286    uint8 idx;
00287 
00288    idx = ecx_getindex(port);
00289    ecx_setupdatagram(port, &(port->txbuf[idx]), EC_CMD_FRMW, idx, ADP, ADO, length, data);
00290    wkc = ecx_srconfirm(port, idx, timeout);
00291    if (wkc > 0)
00292    {
00293       memcpy(data, &(port->rxbuf[idx][EC_HEADERSIZE]), length);
00294    }
00295    ecx_setbufstat(port, idx, EC_BUF_EMPTY);
00296 
00297    return wkc;
00298 }
00299 
00308 uint16 ecx_APRDw(ecx_portt *port, uint16 ADP, uint16 ADO, int timeout)
00309 {
00310    uint16 w;
00311 
00312    w = 0;
00313    ecx_APRD(port, ADP, ADO, sizeof(w), &w, timeout);
00314 
00315    return w;
00316 }
00317 
00328 int ecx_FPRD(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00329 {
00330    int wkc;
00331    uint8 idx;
00332 
00333    idx = ecx_getindex(port);
00334    ecx_setupdatagram(port, &(port->txbuf[idx]), EC_CMD_FPRD, idx, ADP, ADO, length, data);
00335    wkc = ecx_srconfirm(port, idx, timeout);
00336    if (wkc > 0)
00337    {
00338       memcpy(data, &(port->rxbuf[idx][EC_HEADERSIZE]), length);
00339    }
00340    ecx_setbufstat(port, idx, EC_BUF_EMPTY);
00341 
00342    return wkc;
00343 }
00344 
00353 uint16 ecx_FPRDw(ecx_portt *port, uint16 ADP, uint16 ADO, int timeout)
00354 {
00355    uint16 w;
00356 
00357    w = 0;
00358    ecx_FPRD(port, ADP, ADO, sizeof(w), &w, timeout);
00359    return w;
00360 }
00361 
00372 int ecx_APWR(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00373 {
00374    uint8 idx;
00375    int wkc;
00376 
00377    idx = ecx_getindex(port);
00378    ecx_setupdatagram(port, &(port->txbuf[idx]), EC_CMD_APWR, idx, ADP, ADO, length, data);
00379    wkc = ecx_srconfirm(port, idx, timeout);
00380    ecx_setbufstat(port, idx, EC_BUF_EMPTY);
00381    
00382    return wkc;
00383 }
00384 
00394 int ecx_APWRw(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 data, int timeout)
00395 {
00396    return ecx_APWR(port, ADP, ADO, sizeof(data), &data, timeout);
00397 }
00398 
00409 int ecx_FPWR(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00410 {
00411    int wkc;
00412    uint8 idx;
00413 
00414    idx = ecx_getindex(port);
00415    ecx_setupdatagram(port, &(port->txbuf[idx]), EC_CMD_FPWR, idx, ADP, ADO, length, data);
00416    wkc = ecx_srconfirm(port, idx, timeout);
00417    ecx_setbufstat(port, idx, EC_BUF_EMPTY);
00418 
00419    return wkc;
00420 }
00421 
00431 int ecx_FPWRw(ecx_portt *port, uint16 ADP, uint16 ADO, uint16 data, int timeout)
00432 {
00433    return ecx_FPWR(port, ADP, ADO, sizeof(data), &data, timeout);
00434 }
00435 
00445 int ecx_LRW(ecx_portt *port, uint32 LogAdr, uint16 length, void *data, int timeout)
00446 {
00447    uint8 idx;
00448    int wkc;
00449 
00450    idx = ecx_getindex(port);
00451    ecx_setupdatagram(port, &(port->txbuf[idx]), EC_CMD_LRW, idx, LO_WORD(LogAdr), HI_WORD(LogAdr), length, data);
00452    wkc = ecx_srconfirm(port, idx, timeout);
00453    if ((wkc > 0) && (port->rxbuf[idx][EC_CMDOFFSET] == EC_CMD_LRW))
00454    {
00455       memcpy(data, &(port->rxbuf[idx][EC_HEADERSIZE]), length);
00456    }
00457    ecx_setbufstat(port, idx, EC_BUF_EMPTY);
00458 
00459    return wkc;
00460 }
00461 
00471 int ecx_LRD(ecx_portt *port, uint32 LogAdr, uint16 length, void *data, int timeout)
00472 {
00473    uint8 idx;
00474    int wkc;
00475 
00476    idx = ecx_getindex(port);
00477    ecx_setupdatagram(port, &(port->txbuf[idx]), EC_CMD_LRD, idx, LO_WORD(LogAdr), HI_WORD(LogAdr), length, data);
00478    wkc = ecx_srconfirm(port, idx, timeout);
00479    if ((wkc > 0) && (port->rxbuf[idx][EC_CMDOFFSET]==EC_CMD_LRD))
00480    {
00481       memcpy(data, &(port->rxbuf[idx][EC_HEADERSIZE]), length);
00482    }
00483    ecx_setbufstat(port, idx, EC_BUF_EMPTY);
00484 
00485    return wkc;
00486 }
00487 
00497 int ecx_LWR(ecx_portt *port, uint32 LogAdr, uint16 length, void *data, int timeout)
00498 {
00499    uint8 idx;
00500    int wkc;
00501 
00502    idx = ecx_getindex(port);
00503    ecx_setupdatagram(port, &(port->txbuf[idx]), EC_CMD_LWR, idx, LO_WORD(LogAdr), HI_WORD(LogAdr), length, data);
00504    wkc = ecx_srconfirm(port, idx, timeout);
00505    ecx_setbufstat(port, idx, EC_BUF_EMPTY);
00506 
00507    return wkc;
00508 }
00509 
00522 int ecx_LRWDC(ecx_portt *port, uint32 LogAdr, uint16 length, void *data, uint16 DCrs, int64 *DCtime, int timeout)
00523 {
00524    uint16 DCtO;
00525    uint8 idx;
00526    int wkc;
00527    uint64 DCtE;
00528 
00529    idx = ecx_getindex(port);
00530    /* LRW in first datagram */
00531    ecx_setupdatagram(port, &(port->txbuf[idx]), EC_CMD_LRW, idx, LO_WORD(LogAdr), HI_WORD(LogAdr), length, data);
00532    /* FPRMW in second datagram */
00533    DCtE = htoell(*DCtime);
00534    DCtO = ecx_adddatagram(port, &(port->txbuf[idx]), EC_CMD_FRMW, idx, FALSE, DCrs, ECT_REG_DCSYSTIME, sizeof(DCtime), &DCtE);
00535    wkc = ecx_srconfirm(port, idx, timeout);
00536    if ((wkc > 0) && (port->rxbuf[idx][EC_CMDOFFSET] == EC_CMD_LRW))
00537    {
00538       memcpy(data, &(port->rxbuf[idx][EC_HEADERSIZE]), length);
00539       memcpy(&wkc, &(port->rxbuf[idx][EC_HEADERSIZE + length]), EC_WKCSIZE);
00540       memcpy(&DCtE, &(port->rxbuf[idx][DCtO]), sizeof(*DCtime));
00541       *DCtime = etohll(DCtE);
00542    }
00543    ecx_setbufstat(port, idx, EC_BUF_EMPTY);
00544 
00545    return wkc;
00546 }
00547 
00548 #ifdef EC_VER1
00549 int ec_setupdatagram(void *frame, uint8 com, uint8 idx, uint16 ADP, uint16 ADO, uint16 length, void *data)
00550 {
00551    return ecx_setupdatagram (&ecx_port, frame, com, idx, ADP, ADO, length, data);
00552 }
00553 
00554 int ec_adddatagram (void *frame, uint8 com, uint8 idx, boolean more, uint16 ADP, uint16 ADO, uint16 length, void *data)
00555 {
00556    return ecx_adddatagram (&ecx_port, frame, com, idx, more, ADP, ADO, length, data);
00557 }
00558 
00559 int ec_BWR(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00560 {
00561    return ecx_BWR (&ecx_port, ADP, ADO, length, data, timeout);
00562 }
00563 
00564 int ec_BRD(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00565 {
00566    return ecx_BRD(&ecx_port, ADP, ADO, length, data, timeout);
00567 }
00568 
00569 int ec_APRD(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00570 {
00571    return ecx_APRD(&ecx_port, ADP, ADO, length, data, timeout);
00572 }
00573 
00574 int ec_ARMW(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00575 {
00576    return ecx_ARMW(&ecx_port, ADP, ADO, length, data, timeout);
00577 }
00578 
00579 int ec_FRMW(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00580 {
00581    return ecx_FRMW(&ecx_port, ADP, ADO, length, data, timeout);
00582 }
00583 
00584 uint16 ec_APRDw(uint16 ADP, uint16 ADO, int timeout)
00585 {
00586    uint16 w;
00587 
00588    w = 0;
00589    ec_APRD(ADP, ADO, sizeof(w), &w, timeout);
00590 
00591    return w;
00592 }
00593 
00594 int ec_FPRD(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00595 {
00596    return ecx_FPRD(&ecx_port, ADP, ADO, length, data, timeout);
00597 }
00598 
00599 uint16 ec_FPRDw(uint16 ADP, uint16 ADO, int timeout)
00600 {
00601    uint16 w;
00602 
00603    w = 0;
00604    ec_FPRD(ADP, ADO, sizeof(w), &w, timeout);
00605    return w;
00606 }
00607 
00608 int ec_APWR(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00609 {
00610    return ecx_APWR(&ecx_port, ADP, ADO, length, data, timeout);
00611 }
00612 
00613 int ec_APWRw(uint16 ADP, uint16 ADO, uint16 data, int timeout)
00614 {
00615    return ec_APWR(ADP, ADO, sizeof(data), &data, timeout);
00616 }
00617 
00618 int ec_FPWR(uint16 ADP, uint16 ADO, uint16 length, void *data, int timeout)
00619 {
00620    return ecx_FPWR(&ecx_port, ADP, ADO, length, data, timeout);
00621 }
00622 
00623 int ec_FPWRw(uint16 ADP, uint16 ADO, uint16 data, int timeout)
00624 {
00625    return ec_FPWR(ADP, ADO, sizeof(data), &data, timeout);
00626 }
00627 
00628 int ec_LRW(uint32 LogAdr, uint16 length, void *data, int timeout)
00629 {
00630    return ecx_LRW(&ecx_port, LogAdr, length, data, timeout);
00631 }
00632 
00633 int ec_LRD(uint32 LogAdr, uint16 length, void *data, int timeout)
00634 {
00635    return ecx_LRD(&ecx_port, LogAdr, length, data, timeout);
00636 }
00637 
00638 int ec_LWR(uint32 LogAdr, uint16 length, void *data, int timeout)
00639 {
00640    return ecx_LWR(&ecx_port, LogAdr, length, data, timeout);
00641 }
00642 
00643 int ec_LRWDC(uint32 LogAdr, uint16 length, void *data, uint16 DCrs, int64 *DCtime, int timeout)
00644 {
00645    return ecx_LRWDC(&ecx_port, LogAdr, length, data, DCrs, DCtime, timeout);
00646 }
00647 #endif


ethercat_soem
Author(s): Arthur Ketels, M.J.G. van de Molengraft
autogenerated on Wed Aug 26 2015 11:32:40