ethercatconfig.c
Go to the documentation of this file.
00001 /*
00002  * Simple Open EtherCAT Master Library 
00003  *
00004  * File    : ethercatconfig.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 
00049 #include <stdio.h>
00050 #include <string.h>
00051 #include "ethercat_soem/osal.h"
00052 #include "ethercat_soem/oshw.h"
00053 #include "ethercat_soem/ethercattype.h"
00054 #include "ethercat_soem/ethercatbase.h"
00055 #include "ethercat_soem/ethercatmain.h"
00056 #include "ethercat_soem/ethercatcoe.h"
00057 #include "ethercat_soem/ethercatsoe.h"
00058 #include "ethercat_soem/ethercatconfig.h"
00059 
00060 // define if debug printf is needed
00061 //#define EC_DEBUG
00062 
00063 #ifdef EC_DEBUG
00064 #define EC_PRINT printf
00065 #else
00066 #define EC_PRINT(...) do {} while (0)
00067 #endif
00068 
00069 #ifdef EC_VER1
00070 
00071 typedef const struct
00072 {
00074    uint32           man;
00076    uint32           id;
00078    char             name[EC_MAXNAME + 1];
00080    uint8            Dtype;
00082    uint16            Ibits;
00084    uint16           Obits;
00086    uint16           SM2a;
00088    uint32           SM2f;
00090    uint16           SM3a;
00092    uint32           SM3f;
00094    uint8            FM0ac;
00096    uint8            FM1ac;
00097 } ec_configlist_t;
00098 
00099 #include "ethercat_soem/ethercatconfiglist.h"
00100 #endif
00101 
00103 #define EC_DEFAULTMBXSM0  0x00010026
00104 
00105 #define EC_DEFAULTMBXSM1  0x00010022
00106 
00107 #define EC_DEFAULTDOSM0   0x00010044
00108 
00109 #ifdef EC_VER1
00110 
00116 int ec_findconfig( uint32 man, uint32 id)
00117 {
00118    int i = 0;
00119 
00120    do 
00121    {
00122       i++;
00123    } while ( (ec_configlist[i].man != EC_CONFIGEND) && 
00124            ((ec_configlist[i].man != man) || (ec_configlist[i].id != id)) );
00125    if (ec_configlist[i].man == EC_CONFIGEND)
00126    {
00127       i = 0;
00128    }
00129    return i;
00130 }
00131 #endif
00132 
00139 int ecx_config_init(ecx_contextt *context, uint8 usetable)
00140 {
00141    uint16 w, slave, ADPh, configadr, ssigen;
00142    uint16 topology, estat;
00143    int16 topoc, slavec, aliasadr;
00144    uint8 b,h;
00145    uint8 zbuf[64];
00146    uint8 SMc;
00147    uint32 eedat;
00148    int wkc, cindex, nSM, lp;
00149 
00150    EC_PRINT("ec_config_init %d\n",usetable);
00151    *(context->slavecount) = 0;
00152    /* clean ec_slave array */
00153    memset(context->slavelist, 0x00, sizeof(ec_slavet) * context->maxslave);
00154    memset(&zbuf, 0x00, sizeof(zbuf));
00155    memset(context->grouplist, 0x00, sizeof(ec_groupt) * context->maxgroup);
00156    /* clear slave eeprom cache */
00157    ecx_siigetbyte(context, 0, EC_MAXEEPBUF);
00158    
00159    for(lp = 0; lp < context->maxgroup; lp++)
00160    {
00161       context->grouplist[lp].logstartaddr = lp << 16; /* default start address per group entry */
00162    }
00163    /* make special pre-init register writes to enable MAC[1] local administered bit *
00164     * setting for old netX100 slaves */
00165    b = 0x00;
00166    ecx_BWR(context->port, 0x0000, ECT_REG_DLALIAS, sizeof(b), &b, EC_TIMEOUTRET3);    /* Ignore Alias register */
00167    b = EC_STATE_INIT | EC_STATE_ACK;
00168    ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET3);      /* Reset all slaves to Init */
00169    /* netX100 should now be happy */
00170    
00171    wkc = ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET3);      /* Reset all slaves to Init */
00172    printf("wkc = %d\n",wkc);
00173    
00174    w = 0x0000;
00175    wkc = ecx_BRD(context->port, 0x0000, ECT_REG_TYPE, sizeof(w), &w, EC_TIMEOUTSAFE);   /* detect number of slaves */
00176    if (wkc > 0)
00177    {
00178       *(context->slavecount) = wkc;
00179       b = 0x00;
00180       ecx_BWR(context->port, 0x0000, ECT_REG_DLPORT, sizeof(b), &b, EC_TIMEOUTRET3);     /* deact loop manual */
00181       w = htoes(0x0004);
00182       ecx_BWR(context->port, 0x0000, ECT_REG_IRQMASK, sizeof(w), &w, EC_TIMEOUTRET3);    /* set IRQ mask */
00183       ecx_BWR(context->port, 0x0000, ECT_REG_RXERR, 8, &zbuf, EC_TIMEOUTRET3);           /* reset CRC counters */
00184       ecx_BWR(context->port, 0x0000, ECT_REG_FMMU0, 16 * 3, &zbuf, EC_TIMEOUTRET3);      /* reset FMMU's */
00185       ecx_BWR(context->port, 0x0000, ECT_REG_SM0, 8 * 4, &zbuf, EC_TIMEOUTRET3);         /* reset SyncM */
00186       ecx_BWR(context->port, 0x0000, ECT_REG_DCSYSTIME, 4, &zbuf, EC_TIMEOUTRET3);       /* reset system time+ofs */
00187       w = htoes(0x1000);
00188       ecx_BWR(context->port, 0x0000, ECT_REG_DCSPEEDCNT, sizeof(w), &w, EC_TIMEOUTRET3); /* DC speedstart */
00189       w = htoes(0x0c00);
00190       ecx_BWR(context->port, 0x0000, ECT_REG_DCTIMEFILT, sizeof(w), &w, EC_TIMEOUTRET3); /* DC filt expr */
00191       b = 0x00;
00192       ecx_BWR(context->port, 0x0000, ECT_REG_DLALIAS, sizeof(b), &b, EC_TIMEOUTRET3);    /* Ignore Alias register */
00193       b = EC_STATE_INIT | EC_STATE_ACK;
00194       ecx_BWR(context->port, 0x0000, ECT_REG_ALCTL, sizeof(b), &b, EC_TIMEOUTRET3);      /* Reset all slaves to Init */
00195       b = 2;
00196       ecx_BWR(context->port, 0x0000, ECT_REG_EEPCFG, sizeof(b), &b , EC_TIMEOUTRET3);    /* force Eeprom from PDI */
00197       b = 0;
00198       ecx_BWR(context->port, 0x0000, ECT_REG_EEPCFG, sizeof(b), &b , EC_TIMEOUTRET3);    /* set Eeprom to master */
00199       
00200       for (slave = 1; slave <= *(context->slavecount); slave++)
00201       {
00202          ADPh = (uint16)(1 - slave);
00203          context->slavelist[slave].Itype = 
00204             etohs(ecx_APRDw(context->port, ADPh, ECT_REG_PDICTL, EC_TIMEOUTRET3)); /* read interface type of slave */
00205          /* a node offset is used to improve readibility of network frames */
00206          /* this has no impact on the number of addressable slaves (auto wrap around) */
00207          ecx_APWRw(context->port, ADPh, ECT_REG_STADR, htoes(slave + EC_NODEOFFSET) , EC_TIMEOUTRET3); /* set node address of slave */
00208          if (slave == 1) 
00209          {
00210             b = 1; /* kill non ecat frames for first slave */
00211          }
00212          else 
00213          {
00214             b = 0; /* pass all frames for following slaves */
00215          }
00216          ecx_APWRw(context->port, ADPh, ECT_REG_DLCTL, htoes(b), EC_TIMEOUTRET3); /* set non ecat frame behaviour */
00217          configadr = etohs(ecx_APRDw(context->port, ADPh, ECT_REG_STADR, EC_TIMEOUTRET3));
00218          context->slavelist[slave].configadr = configadr;
00219          ecx_FPRD(context->port, configadr, ECT_REG_ALIAS, sizeof(aliasadr), &aliasadr, EC_TIMEOUTRET3);
00220          context->slavelist[slave].aliasadr = etohs(aliasadr);
00221          ecx_FPRD(context->port, configadr, ECT_REG_EEPSTAT, sizeof(estat), &estat, EC_TIMEOUTRET3);
00222          estat = etohs(estat);
00223          if (estat & EC_ESTAT_R64) /* check if slave can read 8 byte chunks */
00224          {
00225             context->slavelist[slave].eep_8byte = 1;
00226          }
00227          ecx_readeeprom1(context, slave, ECT_SII_MANUF); /* Manuf */
00228       }
00229       for (slave = 1; slave <= *(context->slavecount); slave++)
00230       {
00231          context->slavelist[slave].eep_man = 
00232             etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* Manuf */
00233          ecx_readeeprom1(context, slave, ECT_SII_ID); /* ID */
00234       }
00235       for (slave = 1; slave <= *(context->slavecount); slave++)
00236       {
00237          context->slavelist[slave].eep_id = 
00238             etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* ID */
00239          ecx_readeeprom1(context, slave, ECT_SII_REV); /* revision */
00240       }
00241       for (slave = 1; slave <= *(context->slavecount); slave++)
00242       {
00243          context->slavelist[slave].eep_rev = 
00244             etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* revision */
00245          ecx_readeeprom1(context, slave, ECT_SII_RXMBXADR); /* write mailbox address + mailboxsize */
00246       }
00247       for (slave = 1; slave <= *(context->slavecount); slave++)
00248       {
00249          eedat = etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* write mailbox address and mailboxsize */
00250          context->slavelist[slave].mbx_wo = (uint16)LO_WORD(eedat);
00251          context->slavelist[slave].mbx_l = (uint16)HI_WORD(eedat);
00252          if (context->slavelist[slave].mbx_l > 0) 
00253          {
00254             ecx_readeeprom1(context, slave, ECT_SII_TXMBXADR); /* read mailbox offset */
00255          }
00256       }
00257       for (slave = 1; slave <= *(context->slavecount); slave++)
00258       {
00259          if (context->slavelist[slave].mbx_l > 0) 
00260          {
00261             eedat = etohl(ecx_readeeprom2(context, slave, EC_TIMEOUTEEP)); /* read mailbox offset */
00262             context->slavelist[slave].mbx_ro = (uint16)LO_WORD(eedat); /* read mailbox offset */
00263             context->slavelist[slave].mbx_rl = (uint16)HI_WORD(eedat); /*read mailbox length */
00264             if (context->slavelist[slave].mbx_rl == 0)
00265             {
00266                context->slavelist[slave].mbx_rl = context->slavelist[slave].mbx_l;
00267             }
00268          }
00269          configadr = context->slavelist[slave].configadr;
00270          if ((etohs(ecx_FPRDw(context->port, configadr, ECT_REG_ESCSUP, EC_TIMEOUTRET3)) & 0x04) > 0)  /* Support DC? */
00271          {   
00272             context->slavelist[slave].hasdc = TRUE;
00273          }
00274          else
00275          {
00276             context->slavelist[slave].hasdc = FALSE;
00277          }
00278          topology = etohs(ecx_FPRDw(context->port, configadr, ECT_REG_DLSTAT, EC_TIMEOUTRET3)); /* extract topology from DL status */
00279          h = 0; 
00280          b = 0;
00281          if ((topology & 0x0300) == 0x0200) /* port0 open and communication established */
00282          {
00283             h++;
00284             b |= 0x01;
00285          }
00286          if ((topology & 0x0c00) == 0x0800) /* port1 open and communication established */
00287          {
00288             h++;
00289             b |= 0x02;
00290          }
00291          if ((topology & 0x3000) == 0x2000) /* port2 open and communication established */
00292          {
00293             h++;
00294             b |= 0x04;
00295          }
00296          if ((topology & 0xc000) == 0x8000) /* port3 open and communication established */
00297          {
00298             h++;
00299             b |= 0x08;
00300          }
00301          /* ptype = Physical type*/
00302          context->slavelist[slave].ptype = 
00303             LO_BYTE(etohs(ecx_FPRDw(context->port, configadr, ECT_REG_PORTDES, EC_TIMEOUTRET3)));
00304          context->slavelist[slave].topology = h;
00305          context->slavelist[slave].activeports = b;
00306          /* 0=no links, not possible             */
00307          /* 1=1 link  , end of line              */
00308          /* 2=2 links , one before and one after */
00309          /* 3=3 links , split point              */
00310          /* 4=4 links , cross point              */
00311          /* search for parent */
00312          context->slavelist[slave].parent = 0; /* parent is master */
00313          if (slave > 1)
00314          {
00315             topoc = 0; 
00316             slavec = slave - 1;
00317             do
00318             {
00319                topology = context->slavelist[slavec].topology;
00320                if (topology == 1)
00321                {
00322                   topoc--; /* endpoint found */
00323                }
00324                if (topology == 3)
00325                {
00326                   topoc++; /* split found */
00327                }
00328                if (topology == 4)
00329                {
00330                   topoc += 2; /* cross found */
00331                }
00332                if (((topoc >= 0) && (topology > 1)) ||
00333                    (slavec == 1)) /* parent found */
00334                {
00335                   context->slavelist[slave].parent = slavec;
00336                   slavec = 1;
00337                }
00338                slavec--;
00339             }
00340             while (slavec > 0);
00341          }
00342 
00343          w = ecx_statecheck(context, slave, EC_STATE_INIT,  EC_TIMEOUTSTATE); //* check state change Init */
00344    
00345          /* set default mailbox configuration if slave has mailbox */
00346          if (context->slavelist[slave].mbx_l>0)
00347          {   
00348             context->slavelist[slave].SMtype[0] = 1;
00349             context->slavelist[slave].SMtype[1] = 2;
00350             context->slavelist[slave].SMtype[2] = 3;
00351             context->slavelist[slave].SMtype[3] = 4;
00352             context->slavelist[slave].SM[0].StartAddr = htoes(context->slavelist[slave].mbx_wo);
00353             context->slavelist[slave].SM[0].SMlength = htoes(context->slavelist[slave].mbx_l);
00354             context->slavelist[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0);
00355             context->slavelist[slave].SM[1].StartAddr = htoes(context->slavelist[slave].mbx_ro);
00356             context->slavelist[slave].SM[1].SMlength = htoes(context->slavelist[slave].mbx_rl);
00357             context->slavelist[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1);
00358             context->slavelist[slave].mbx_proto = 
00359                ecx_readeeprom(context, slave, ECT_SII_MBXPROTO, EC_TIMEOUTEEP);
00360          }   
00361          cindex = 0;
00362          #ifdef EC_VER1
00363          /* use configuration table ? */
00364          if (usetable)
00365          {
00366             cindex = ec_findconfig( context->slavelist[slave].eep_man, context->slavelist[slave].eep_id );
00367             context->slavelist[slave].configindex= cindex;
00368          }
00369          /* slave found in configuration table ? */
00370          if (cindex)
00371          {
00372             context->slavelist[slave].Dtype = ec_configlist[cindex].Dtype;            
00373             strcpy(context->slavelist[slave].name ,ec_configlist[cindex].name);
00374             context->slavelist[slave].Ibits = ec_configlist[cindex].Ibits;
00375             context->slavelist[slave].Obits = ec_configlist[cindex].Obits;
00376             if (context->slavelist[slave].Obits)
00377             {
00378                context->slavelist[slave].FMMU0func = 1;
00379             }
00380             if (context->slavelist[slave].Ibits)
00381             {
00382                context->slavelist[slave].FMMU1func = 2;
00383             }
00384             context->slavelist[slave].FMMU[0].FMMUactive = ec_configlist[cindex].FM0ac;
00385             context->slavelist[slave].FMMU[1].FMMUactive = ec_configlist[cindex].FM1ac;
00386             context->slavelist[slave].SM[2].StartAddr = htoes(ec_configlist[cindex].SM2a);
00387             context->slavelist[slave].SM[2].SMflags = htoel(ec_configlist[cindex].SM2f);
00388             /* simple (no mailbox) output slave found ? */
00389             if (context->slavelist[slave].Obits && !context->slavelist[slave].SM[2].StartAddr)
00390             {
00391                context->slavelist[slave].SM[0].StartAddr = htoes(0x0f00);
00392                context->slavelist[slave].SM[0].SMlength = htoes((context->slavelist[slave].Obits + 7) / 8);
00393                context->slavelist[slave].SM[0].SMflags = htoel(EC_DEFAULTDOSM0);         
00394                context->slavelist[slave].FMMU[0].FMMUactive = 1;
00395                context->slavelist[slave].FMMU[0].FMMUtype = 2;
00396                context->slavelist[slave].SMtype[0] = 3;
00397             }
00398             /* complex output slave */
00399             else
00400             {
00401                context->slavelist[slave].SM[2].SMlength = htoes((context->slavelist[slave].Obits + 7) / 8);
00402                context->slavelist[slave].SMtype[2] = 3;
00403             }   
00404             context->slavelist[slave].SM[3].StartAddr = htoes(ec_configlist[cindex].SM3a);
00405             context->slavelist[slave].SM[3].SMflags = htoel(ec_configlist[cindex].SM3f);
00406             /* simple (no mailbox) input slave found ? */
00407             if (context->slavelist[slave].Ibits && !context->slavelist[slave].SM[3].StartAddr)
00408             {
00409                context->slavelist[slave].SM[1].StartAddr = htoes(0x1000);
00410                context->slavelist[slave].SM[1].SMlength = htoes((context->slavelist[slave].Ibits + 7) / 8);
00411                context->slavelist[slave].SM[1].SMflags = htoel(0x00000000);         
00412                context->slavelist[slave].FMMU[1].FMMUactive = 1;
00413                context->slavelist[slave].FMMU[1].FMMUtype = 1;
00414                context->slavelist[slave].SMtype[1] = 4;
00415             }
00416             /* complex input slave */
00417             else
00418             {
00419                context->slavelist[slave].SM[3].SMlength = htoes((context->slavelist[slave].Ibits + 7) / 8);
00420                context->slavelist[slave].SMtype[3] = 4;
00421             }   
00422          }
00423          /* slave not in configuration table, find out via SII */
00424          else
00425          #endif
00426          {
00427             ssigen = ecx_siifind(context, slave, ECT_SII_GENERAL);
00428             /* SII general section */
00429             if (ssigen)
00430             {
00431                context->slavelist[slave].CoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x07);
00432                context->slavelist[slave].FoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x08);
00433                context->slavelist[slave].EoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x09);
00434                context->slavelist[slave].SoEdetails = ecx_siigetbyte(context, slave, ssigen + 0x0a);
00435                if((ecx_siigetbyte(context, slave, ssigen + 0x0d) & 0x02) > 0)
00436                {
00437                   context->slavelist[slave].blockLRW = 1;
00438                   context->slavelist[0].blockLRW++;                  
00439                }   
00440                context->slavelist[slave].Ebuscurrent = ecx_siigetbyte(context, slave, ssigen + 0x0e);
00441                context->slavelist[slave].Ebuscurrent += ecx_siigetbyte(context, slave, ssigen + 0x0f) << 8;
00442                context->slavelist[0].Ebuscurrent += context->slavelist[slave].Ebuscurrent;
00443             }
00444             /* SII strings section */
00445             if (ecx_siifind(context, slave, ECT_SII_STRING) > 0)
00446             {
00447                ecx_siistring(context, context->slavelist[slave].name, slave, 1);
00448             }
00449             /* no name for slave found, use constructed name */
00450             else
00451             {
00452                sprintf(context->slavelist[slave].name, "? M:%8.8x I:%8.8x",
00453                        (unsigned int)context->slavelist[slave].eep_man, 
00454                        (unsigned int)context->slavelist[slave].eep_id);
00455             }
00456             /* SII SM section */
00457             nSM = ecx_siiSM(context, slave, context->eepSM);
00458             if (nSM>0)
00459             {   
00460                context->slavelist[slave].SM[0].StartAddr = htoes(context->eepSM->PhStart);
00461                context->slavelist[slave].SM[0].SMlength = htoes(context->eepSM->Plength);
00462                context->slavelist[slave].SM[0].SMflags = 
00463                   htoel((context->eepSM->Creg) + (context->eepSM->Activate << 16));
00464                SMc = 1;
00465                while ((SMc < EC_MAXSM) &&  ecx_siiSMnext(context, slave, context->eepSM, SMc))
00466                {
00467                   context->slavelist[slave].SM[SMc].StartAddr = htoes(context->eepSM->PhStart);
00468                   context->slavelist[slave].SM[SMc].SMlength = htoes(context->eepSM->Plength);
00469                   context->slavelist[slave].SM[SMc].SMflags = 
00470                      htoel((context->eepSM->Creg) + (context->eepSM->Activate << 16));
00471                   SMc++;
00472                }   
00473             }   
00474             /* SII FMMU section */
00475             if (ecx_siiFMMU(context, slave, context->eepFMMU))
00476             {
00477                if (context->eepFMMU->FMMU0 !=0xff) 
00478                {
00479                   context->slavelist[slave].FMMU0func = context->eepFMMU->FMMU0;
00480                }
00481                if (context->eepFMMU->FMMU1 !=0xff) 
00482                {
00483                   context->slavelist[slave].FMMU1func = context->eepFMMU->FMMU1;
00484                }
00485                if (context->eepFMMU->FMMU2 !=0xff) 
00486                {
00487                   context->slavelist[slave].FMMU2func = context->eepFMMU->FMMU2;
00488                }
00489                if (context->eepFMMU->FMMU3 !=0xff) 
00490                {
00491                   context->slavelist[slave].FMMU3func = context->eepFMMU->FMMU3;
00492                }
00493             }            
00494          }   
00495 
00496          if (context->slavelist[slave].mbx_l > 0)
00497          {
00498             if (context->slavelist[slave].SM[0].StartAddr == 0x0000) /* should never happen */
00499             {
00500                EC_PRINT("Slave %d has no proper mailbox in configuration, try default.\n", slave);
00501                context->slavelist[slave].SM[0].StartAddr = htoes(0x1000);
00502                context->slavelist[slave].SM[0].SMlength = htoes(0x0080);
00503                context->slavelist[slave].SM[0].SMflags = htoel(EC_DEFAULTMBXSM0);
00504                context->slavelist[slave].SMtype[0] = 1;               
00505             }         
00506             if (context->slavelist[slave].SM[1].StartAddr == 0x0000) /* should never happen */
00507             {
00508                EC_PRINT("Slave %d has no proper mailbox out configuration, try default.\n", slave);
00509                context->slavelist[slave].SM[1].StartAddr = htoes(0x1080);
00510                context->slavelist[slave].SM[1].SMlength = htoes(0x0080);
00511                context->slavelist[slave].SM[1].SMflags = htoel(EC_DEFAULTMBXSM1);
00512                context->slavelist[slave].SMtype[1] = 2;
00513             }         
00514             /* program SM0 mailbox in and SM1 mailbox out for slave */
00515             /* writing both SM in one datagram will solve timing issue in old NETX */
00516             ecx_FPWR(context->port, configadr, ECT_REG_SM0, sizeof(ec_smt) * 2, 
00517                &(context->slavelist[slave].SM[0]), EC_TIMEOUTRET3);
00518          } 
00519          /* request pre_op for slave */
00520          ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_PRE_OP | EC_STATE_ACK) , EC_TIMEOUTRET3); /* set preop status */
00521       }
00522    }   
00523    return wkc;
00524 }
00525 
00533 int ecx_config_map_group(ecx_contextt *context, void *pIOmap, uint8 group)
00534 {
00535    uint16 slave, configadr;
00536    int Isize, Osize, BitCount, ByteCount, FMMUsize, FMMUdone;
00537    uint16 SMlength, EndAddr;
00538    uint8 BitPos;
00539    uint8 SMc, FMMUc;
00540    uint32 LogAddr = 0;
00541    uint32 oLogAddr = 0;
00542    uint32 diff;
00543    int nSM, rval;
00544    ec_eepromPDOt eepPDO;
00545    uint16 currentsegment = 0;
00546    uint32 segmentsize = 0;
00547 
00548    if ((*(context->slavecount) > 0) && (group < context->maxgroup))
00549    {   
00550       EC_PRINT("ec_config_map_group IOmap:%p group:%d\n", pIOmap, group);
00551       LogAddr = context->grouplist[group].logstartaddr;
00552       oLogAddr = LogAddr;
00553       BitPos = 0;
00554       context->grouplist[group].nsegments = 0;
00555       context->grouplist[group].outputsWKC = 0;
00556       context->grouplist[group].inputsWKC = 0;
00557 
00558       /* find output mapping of slave and program FMMU */
00559       for (slave = 1; slave <= *(context->slavecount); slave++)
00560       {
00561          configadr = context->slavelist[slave].configadr;
00562 
00563          ecx_statecheck(context, slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE); /* check state change pre-op */
00564 
00565          EC_PRINT(" >Slave %d, configadr %x, state %2.2x\n",
00566                   slave, context->slavelist[slave].configadr, context->slavelist[slave].state);
00567 
00568          /* execute special slave configuration hook Pre-Op to Safe-OP */
00569          if(context->slavelist[slave].PO2SOconfig) /* only if registered */
00570          {
00571             context->slavelist[slave].PO2SOconfig(slave);         
00572          }
00573          if (!group || (group == context->slavelist[slave].group))
00574          {   
00575          
00576             /* if slave not found in configlist find IO mapping in slave self */
00577             if (!context->slavelist[slave].configindex)
00578             {
00579                Isize = 0;
00580                Osize = 0;
00581                if (context->slavelist[slave].mbx_proto & ECT_MBXPROT_COE) /* has CoE */
00582                {
00583                   rval = 0;
00584                   if (context->slavelist[slave].CoEdetails & ECT_COEDET_SDOCA) /* has Complete Access */
00585                      /* read PDO mapping via CoE and use Complete Access */
00586                   {
00587                      rval = ecx_readPDOmapCA(context, slave, &Osize, &Isize);
00588                   }
00589                   if (!rval) /* CA not available or not succeeded */
00590                   {
00591                      /* read PDO mapping via CoE */
00592                      rval = ecx_readPDOmap(context, slave, &Osize, &Isize);
00593                   }
00594                   EC_PRINT("  CoE Osize:%d Isize:%d\n", Osize, Isize);
00595                }
00596                if ((!Isize && !Osize) && (context->slavelist[slave].mbx_proto & ECT_MBXPROT_SOE)) /* has SoE */
00597                {
00598                   /* read AT / MDT mapping via SoE */
00599                   rval = ecx_readIDNmap(context, slave, &Osize, &Isize);
00600                   context->slavelist[slave].SM[2].SMlength = htoes((Osize + 7) / 8);
00601                   context->slavelist[slave].SM[3].SMlength = htoes((Isize + 7) / 8);
00602                   EC_PRINT("  SoE Osize:%d Isize:%d\n", Osize, Isize);
00603                }
00604                if (!Isize && !Osize) /* find PDO mapping by SII */
00605                {
00606                   memset(&eepPDO, 0, sizeof(eepPDO));
00607                   Isize = (int)ecx_siiPDO(context, slave, &eepPDO, 0);
00608                   EC_PRINT("  SII Isize:%d\n", Isize);               
00609                   for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
00610                   {   
00611                      if (eepPDO.SMbitsize[nSM] > 0)
00612                      {   
00613                         context->slavelist[slave].SM[nSM].SMlength =  htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
00614                         context->slavelist[slave].SMtype[nSM] = 4;
00615                         EC_PRINT("    SM%d length %d\n", nSM, eepPDO.SMbitsize[nSM]);
00616                      }   
00617                   }   
00618                   Osize = (int)ecx_siiPDO(context, slave, &eepPDO, 1);
00619                   EC_PRINT("  SII Osize:%d\n", Osize);               
00620                   for( nSM=0 ; nSM < EC_MAXSM ; nSM++ )
00621                   {   
00622                      if (eepPDO.SMbitsize[nSM] > 0)
00623                      {   
00624                         context->slavelist[slave].SM[nSM].SMlength =  htoes((eepPDO.SMbitsize[nSM] + 7) / 8);
00625                         context->slavelist[slave].SMtype[nSM] = 3;
00626                         EC_PRINT("    SM%d length %d\n", nSM, eepPDO.SMbitsize[nSM]);
00627                      }   
00628                   }   
00629                }
00630                context->slavelist[slave].Obits = Osize;
00631                context->slavelist[slave].Ibits = Isize;
00632                EC_PRINT("     ISIZE:%d %d OSIZE:%d\n", 
00633                   context->slavelist[slave].Ibits, Isize,context->slavelist[slave].Obits);    
00634             }
00635 
00636             EC_PRINT("  SM programming\n");  
00637             if (!context->slavelist[slave].mbx_l && context->slavelist[slave].SM[0].StartAddr)
00638             {
00639                ecx_FPWR(context->port, configadr, ECT_REG_SM0, 
00640                   sizeof(ec_smt), &(context->slavelist[slave].SM[0]), EC_TIMEOUTRET3);
00641                EC_PRINT("    SM0 Type:%d StartAddr:%4.4x Flags:%8.8x\n", 
00642                    context->slavelist[slave].SMtype[0], 
00643                    context->slavelist[slave].SM[0].StartAddr, 
00644                    context->slavelist[slave].SM[0].SMflags);   
00645             }
00646             if (!context->slavelist[slave].mbx_l && context->slavelist[slave].SM[1].StartAddr)
00647             {
00648                ecx_FPWR(context->port, configadr, ECT_REG_SM1, 
00649                   sizeof(ec_smt), &context->slavelist[slave].SM[1], EC_TIMEOUTRET3);
00650                EC_PRINT("    SM1 Type:%d StartAddr:%4.4x Flags:%8.8x\n", 
00651                    context->slavelist[slave].SMtype[1], 
00652                    context->slavelist[slave].SM[1].StartAddr, 
00653                    context->slavelist[slave].SM[1].SMflags);   
00654             }
00655             /* program SM2 to SMx */
00656             for( nSM = 2 ; nSM < EC_MAXSM ; nSM++ )
00657             {   
00658                if (context->slavelist[slave].SM[nSM].StartAddr)
00659                {
00660                   /* check if SM length is zero -> clear enable flag */
00661                   if( context->slavelist[slave].SM[nSM].SMlength == 0) 
00662                   {
00663                      context->slavelist[slave].SM[nSM].SMflags = 
00664                         htoel( etohl(context->slavelist[slave].SM[nSM].SMflags) & EC_SMENABLEMASK);
00665                   }
00666                   ecx_FPWR(context->port, configadr, ECT_REG_SM0 + (nSM * sizeof(ec_smt)),
00667                      sizeof(ec_smt), &context->slavelist[slave].SM[nSM], EC_TIMEOUTRET3);
00668                   EC_PRINT("    SM%d Type:%d StartAddr:%4.4x Flags:%8.8x\n", nSM,
00669                       context->slavelist[slave].SMtype[nSM], 
00670                       context->slavelist[slave].SM[nSM].StartAddr, 
00671                       context->slavelist[slave].SM[nSM].SMflags);   
00672                }
00673             }
00674             if (context->slavelist[slave].Ibits > 7)
00675             {
00676                context->slavelist[slave].Ibytes = (context->slavelist[slave].Ibits + 7) / 8;
00677             }
00678             if (context->slavelist[slave].Obits > 7)
00679             {
00680                context->slavelist[slave].Obytes = (context->slavelist[slave].Obits + 7) / 8;
00681             }
00682             FMMUc = context->slavelist[slave].FMMUunused;
00683             SMc = 0;
00684             BitCount = 0;
00685             ByteCount = 0;
00686             EndAddr = 0;
00687             FMMUsize = 0;
00688             FMMUdone = 0;
00689             /* create output mapping */
00690             if (context->slavelist[slave].Obits)
00691             {
00692                EC_PRINT("  OUTPUT MAPPING\n");
00693                /* search for SM that contribute to the output mapping */
00694                while ( (SMc < (EC_MAXSM - 1)) && (FMMUdone < ((context->slavelist[slave].Obits + 7) / 8)))
00695                {   
00696                   EC_PRINT("    FMMU %d\n", FMMUc);
00697                   while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 3)) SMc++;
00698                   EC_PRINT("      SM%d\n", SMc);
00699                   context->slavelist[slave].FMMU[FMMUc].PhysStart = 
00700                      context->slavelist[slave].SM[SMc].StartAddr;
00701                   SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
00702                   ByteCount += SMlength;
00703                   BitCount += SMlength * 8;
00704                   EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;
00705                   while ( (BitCount < context->slavelist[slave].Obits) && (SMc < (EC_MAXSM - 1)) ) /* more SM for output */
00706                   {
00707                      SMc++;
00708                      while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 3)) SMc++;
00709                      /* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */
00710                      if ( etohs(context->slavelist[slave].SM[SMc].StartAddr) > EndAddr ) 
00711                      {
00712                         break;
00713                      }
00714                      EC_PRINT("      SM%d\n", SMc);
00715                      SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
00716                      ByteCount += SMlength;
00717                      BitCount += SMlength * 8;
00718                      EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;               
00719                   }   
00720 
00721                   /* bit oriented slave */
00722                   if (!context->slavelist[slave].Obytes)
00723                   {   
00724                      context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
00725                      context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;
00726                      BitPos += context->slavelist[slave].Obits - 1;
00727                      if (BitPos > 7)
00728                      {
00729                         LogAddr++;
00730                         BitPos -= 8;
00731                      }   
00732                      FMMUsize = LogAddr - etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) + 1;
00733                      context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
00734                      context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;
00735                      BitPos ++;
00736                      if (BitPos > 7)
00737                      {
00738                         LogAddr++;
00739                         BitPos -= 8;
00740                      }   
00741                   }
00742                   /* byte oriented slave */
00743                   else
00744                   {
00745                      if (BitPos)
00746                      {
00747                         LogAddr++;
00748                         BitPos = 0;
00749                      }   
00750                      context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
00751                      context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;
00752                      BitPos = 7;
00753                      FMMUsize = ByteCount;
00754                      if ((FMMUsize + FMMUdone)> (int)context->slavelist[slave].Obytes)
00755                      {
00756                         FMMUsize = context->slavelist[slave].Obytes - FMMUdone;
00757                      }
00758                      LogAddr += FMMUsize;
00759                      context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
00760                      context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;
00761                      BitPos = 0;
00762                   }
00763                   FMMUdone += FMMUsize;
00764                   context->slavelist[slave].FMMU[FMMUc].PhysStartBit = 0;
00765                   context->slavelist[slave].FMMU[FMMUc].FMMUtype = 2;
00766                   context->slavelist[slave].FMMU[FMMUc].FMMUactive = 1;
00767                   /* program FMMU for output */
00768                   ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc),
00769                      sizeof(ec_fmmut), &(context->slavelist[slave].FMMU[FMMUc]), EC_TIMEOUTRET3);
00770                   context->grouplist[group].outputsWKC++;
00771                   if (!context->slavelist[slave].outputs)
00772                   {   
00773                      context->slavelist[slave].outputs = 
00774                         (uint8 *)(pIOmap) + etohl(context->slavelist[slave].FMMU[FMMUc].LogStart);
00775                      context->slavelist[slave].Ostartbit = 
00776                         context->slavelist[slave].FMMU[FMMUc].LogStartbit;
00777                      EC_PRINT("    slave %d Outputs %p startbit %d\n", 
00778                         slave, 
00779                         context->slavelist[slave].outputs, 
00780                         context->slavelist[slave].Ostartbit);
00781                   }
00782                   FMMUc++;
00783                }   
00784                context->slavelist[slave].FMMUunused = FMMUc;
00785                diff = LogAddr - oLogAddr;
00786                oLogAddr = LogAddr;
00787                if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
00788                {
00789                   context->grouplist[group].IOsegment[currentsegment] = segmentsize;
00790                   if (currentsegment < (EC_MAXIOSEGMENTS - 1))
00791                   {
00792                      currentsegment++;
00793                      segmentsize = diff;   
00794                   }
00795                }
00796                else
00797                {
00798                   segmentsize += diff;
00799                }
00800             }
00801          }   
00802       }
00803       if (BitPos)
00804       {
00805          LogAddr++;
00806          oLogAddr = LogAddr;
00807          BitPos = 0;
00808          if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
00809          {
00810             context->grouplist[group].IOsegment[currentsegment] = segmentsize;
00811             if (currentsegment < (EC_MAXIOSEGMENTS - 1))
00812             {
00813                currentsegment++;
00814                segmentsize = 1;   
00815             }
00816          }
00817          else
00818          {
00819             segmentsize += 1;
00820          }
00821       }   
00822       context->grouplist[group].outputs = pIOmap;
00823       context->grouplist[group].Obytes = LogAddr;
00824       context->grouplist[group].nsegments = currentsegment + 1;
00825       context->grouplist[group].Isegment = currentsegment;
00826       context->grouplist[group].Ioffset = segmentsize;
00827       if (!group)
00828       {   
00829          context->slavelist[0].outputs = pIOmap;
00830          context->slavelist[0].Obytes = LogAddr; /* store output bytes in master record */
00831       }   
00832       
00833       /* do input mapping of slave and program FMMUs */
00834       for (slave = 1; slave <= *(context->slavecount); slave++)
00835       {
00836          configadr = context->slavelist[slave].configadr;
00837          FMMUc = context->slavelist[slave].FMMUunused;
00838          if (context->slavelist[slave].Obits) /* find free FMMU */
00839          {
00840             while ( context->slavelist[slave].FMMU[FMMUc].LogStart ) FMMUc++;
00841          }
00842          SMc = 0;
00843          BitCount = 0;
00844          ByteCount = 0;
00845          EndAddr = 0;
00846          FMMUsize = 0;
00847          FMMUdone = 0;
00848          /* create input mapping */
00849          if (context->slavelist[slave].Ibits)
00850          {
00851             EC_PRINT(" =Slave %d, INPUT MAPPING\n", slave);
00852             /* search for SM that contribute to the input mapping */
00853             while ( (SMc < (EC_MAXSM - 1)) && (FMMUdone < ((context->slavelist[slave].Ibits + 7) / 8)))
00854             {   
00855                EC_PRINT("    FMMU %d\n", FMMUc);
00856                while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 4)) SMc++;
00857                EC_PRINT("      SM%d\n", SMc);
00858                context->slavelist[slave].FMMU[FMMUc].PhysStart = 
00859                   context->slavelist[slave].SM[SMc].StartAddr;
00860                SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
00861                ByteCount += SMlength;
00862                BitCount += SMlength * 8;
00863                EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;
00864                while ( (BitCount < context->slavelist[slave].Ibits) && (SMc < (EC_MAXSM - 1)) ) /* more SM for input */
00865                {
00866                   SMc++;
00867                   while ( (SMc < (EC_MAXSM - 1)) && (context->slavelist[slave].SMtype[SMc] != 4)) SMc++;
00868                   /* if addresses from more SM connect use one FMMU otherwise break up in mutiple FMMU */
00869                   if ( etohs(context->slavelist[slave].SM[SMc].StartAddr) > EndAddr ) 
00870                   {
00871                      break;
00872                   }
00873                   EC_PRINT("      SM%d\n", SMc);
00874                   SMlength = etohs(context->slavelist[slave].SM[SMc].SMlength);
00875                   ByteCount += SMlength;
00876                   BitCount += SMlength * 8;
00877                   EndAddr = etohs(context->slavelist[slave].SM[SMc].StartAddr) + SMlength;               
00878                }   
00879 
00880                /* bit oriented slave */
00881                if (!context->slavelist[slave].Ibytes)
00882                {   
00883                   context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
00884                   context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;
00885                   BitPos += context->slavelist[slave].Ibits - 1;
00886                   if (BitPos > 7)
00887                   {
00888                      LogAddr++;
00889                      BitPos -= 8;
00890                   }   
00891                   FMMUsize = LogAddr - etohl(context->slavelist[slave].FMMU[FMMUc].LogStart) + 1;
00892                   context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
00893                   context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;
00894                   BitPos ++;
00895                   if (BitPos > 7)
00896                   {
00897                      LogAddr++;
00898                      BitPos -= 8;
00899                   }   
00900                }
00901                /* byte oriented slave */
00902                else
00903                {
00904                   if (BitPos)
00905                   {
00906                      LogAddr++;
00907                      BitPos = 0;
00908                   }   
00909                   context->slavelist[slave].FMMU[FMMUc].LogStart = htoel(LogAddr);
00910                   context->slavelist[slave].FMMU[FMMUc].LogStartbit = BitPos;
00911                   BitPos = 7;
00912                   FMMUsize = ByteCount;
00913                   if ((FMMUsize + FMMUdone)> (int)context->slavelist[slave].Ibytes)
00914                   {
00915                      FMMUsize = context->slavelist[slave].Ibytes - FMMUdone;
00916                   }
00917                   LogAddr += FMMUsize;
00918                   context->slavelist[slave].FMMU[FMMUc].LogLength = htoes(FMMUsize);
00919                   context->slavelist[slave].FMMU[FMMUc].LogEndbit = BitPos;
00920                   BitPos = 0;
00921                }
00922                FMMUdone += FMMUsize;
00923                if (context->slavelist[slave].FMMU[FMMUc].LogLength)
00924                {   
00925                   context->slavelist[slave].FMMU[FMMUc].PhysStartBit = 0;
00926                   context->slavelist[slave].FMMU[FMMUc].FMMUtype = 1;
00927                   context->slavelist[slave].FMMU[FMMUc].FMMUactive = 1;
00928                   /* program FMMU for input */
00929                   ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc), 
00930                      sizeof(ec_fmmut), &(context->slavelist[slave].FMMU[FMMUc]), EC_TIMEOUTRET3);
00931                   /* add one for an input FMMU */
00932                   context->grouplist[group].inputsWKC++;
00933                }   
00934                if (!context->slavelist[slave].inputs)
00935                {   
00936                   context->slavelist[slave].inputs = 
00937                      (uint8 *)(pIOmap) + etohl(context->slavelist[slave].FMMU[FMMUc].LogStart);
00938                   context->slavelist[slave].Istartbit = 
00939                      context->slavelist[slave].FMMU[FMMUc].LogStartbit;
00940                   EC_PRINT("    Inputs %p startbit %d\n", 
00941                      context->slavelist[slave].inputs, 
00942                      context->slavelist[slave].Istartbit);
00943                }
00944                FMMUc++;
00945             }   
00946             context->slavelist[slave].FMMUunused = FMMUc;
00947             diff = LogAddr - oLogAddr;
00948             oLogAddr = LogAddr;
00949             if ((segmentsize + diff) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
00950             {
00951                context->grouplist[group].IOsegment[currentsegment] = segmentsize;
00952                if (currentsegment < (EC_MAXIOSEGMENTS - 1))
00953                {
00954                   currentsegment++;
00955                   segmentsize = diff;   
00956                }
00957             }
00958             else
00959             {
00960                segmentsize += diff;
00961             }   
00962          }
00963 
00964          ecx_eeprom2pdi(context, slave); /* set Eeprom control to PDI */         
00965          ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP) , EC_TIMEOUTRET3); /* set safeop status */
00966                   
00967          if (context->slavelist[slave].blockLRW)
00968          {    
00969             context->grouplist[group].blockLRW++;                     
00970          }
00971          context->grouplist[group].Ebuscurrent += context->slavelist[slave].Ebuscurrent;
00972       }
00973       if (BitPos)
00974       {
00975          LogAddr++;
00976          oLogAddr = LogAddr;
00977          BitPos = 0;
00978          if ((segmentsize + 1) > (EC_MAXLRWDATA - EC_FIRSTDCDATAGRAM))
00979          {
00980             context->grouplist[group].IOsegment[currentsegment] = segmentsize;
00981             if (currentsegment < (EC_MAXIOSEGMENTS - 1))
00982             {
00983                currentsegment++;
00984                segmentsize = 1;   
00985             }
00986          }
00987          else
00988          {
00989             segmentsize += 1;
00990          }
00991       }   
00992       context->grouplist[group].IOsegment[currentsegment] = segmentsize;
00993       context->grouplist[group].nsegments = currentsegment + 1;
00994       context->grouplist[group].inputs = (uint8 *)(pIOmap) + context->grouplist[group].Obytes;
00995       context->grouplist[group].Ibytes = LogAddr - context->grouplist[group].Obytes;
00996       if (!group)
00997       {   
00998          context->slavelist[0].inputs = (uint8 *)(pIOmap) + context->slavelist[0].Obytes;
00999          context->slavelist[0].Ibytes = LogAddr - context->slavelist[0].Obytes; /* store input bytes in master record */
01000       }   
01001 
01002       EC_PRINT("IOmapSize %d\n", LogAddr - context->grouplist[group].logstartaddr);      
01003    
01004       return (LogAddr - context->grouplist[group].logstartaddr);
01005    }
01006    
01007    return 0;
01008 }   
01009 
01017 int ecx_recover_slave(ecx_contextt *context, uint16 slave, int timeout)
01018 {
01019    int rval;
01020    uint16 ADPh, configadr, readadr, wkc;
01021 
01022    rval = 0;
01023    configadr = context->slavelist[slave].configadr;
01024    ADPh = (uint16)(1 - slave);
01025    /* check if we found another slave than the requested */
01026    readadr = 0xfffe;
01027    wkc = ecx_APRD(context->port, ADPh, ECT_REG_STADR, sizeof(readadr), &readadr, timeout);
01028    /* correct slave found, finished */
01029    if(readadr == configadr)
01030    {
01031        return 1;
01032    }
01033    /* only try if no config address*/
01034    if( (wkc > 0) && (readadr == 0))
01035    {
01036       /* clear possible slaves at EC_TEMPNODE */
01037       ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , 0);
01038       /* set temporary node address of slave */
01039       if(ecx_APWRw(context->port, ADPh, ECT_REG_STADR, htoes(EC_TEMPNODE) , timeout) <= 0)
01040       {   
01041          ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , 0);
01042          return 0; /* slave fails to respond */
01043       }
01044    
01045       context->slavelist[slave].configadr = EC_TEMPNODE; /* temporary config address */   
01046       ecx_eeprom2master(context, slave); /* set Eeprom control to master */         
01047 
01048       /* check if slave is the same as configured before */
01049       if ((ecx_FPRDw(context->port, EC_TEMPNODE, ECT_REG_ALIAS, timeout) == 
01050              context->slavelist[slave].aliasadr) &&
01051           (ecx_readeeprom(context, slave, ECT_SII_ID, EC_TIMEOUTEEP) == 
01052              context->slavelist[slave].eep_id) &&
01053           (ecx_readeeprom(context, slave, ECT_SII_MANUF, EC_TIMEOUTEEP) == 
01054              context->slavelist[slave].eep_man) &&
01055           (ecx_readeeprom(context, slave, ECT_SII_REV, EC_TIMEOUTEEP) == 
01056              context->slavelist[slave].eep_rev))
01057       {
01058          rval = ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(configadr) , timeout);
01059          context->slavelist[slave].configadr = configadr;
01060       }
01061       else
01062       {
01063          /* slave is not the expected one, remove config address*/
01064          ecx_FPWRw(context->port, EC_TEMPNODE, ECT_REG_STADR, htoes(0) , timeout);
01065          context->slavelist[slave].configadr = configadr;
01066       }
01067    }
01068 
01069    return rval;
01070 }
01071 
01079 int ecx_reconfig_slave(ecx_contextt *context, uint16 slave, int timeout)
01080 {
01081    int state, nSM, FMMUc;
01082    uint16 configadr;
01083    
01084    configadr = context->slavelist[slave].configadr;
01085    if (ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_INIT) , timeout) <= 0)
01086    {
01087       return 0;
01088    }
01089    state = 0;
01090    ecx_eeprom2pdi(context, slave); /* set Eeprom control to PDI */         
01091    /* check state change init */
01092    state = ecx_statecheck(context, slave, EC_STATE_INIT, EC_TIMEOUTSTATE);
01093    if(state == EC_STATE_INIT)
01094    {
01095       /* program all enabled SM */
01096       for( nSM = 0 ; nSM < EC_MAXSM ; nSM++ )
01097       {   
01098          if (context->slavelist[slave].SM[nSM].StartAddr)
01099          {   
01100             ecx_FPWR(context->port, configadr, ECT_REG_SM0 + (nSM * sizeof(ec_smt)),
01101                sizeof(ec_smt), &context->slavelist[slave].SM[nSM], timeout);
01102          }
01103       }
01104       ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_PRE_OP) , timeout);
01105       state = ecx_statecheck(context, slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE); /* check state change pre-op */
01106       if( state == EC_STATE_PRE_OP)
01107       {
01108          /* execute special slave configuration hook Pre-Op to Safe-OP */
01109          if(context->slavelist[slave].PO2SOconfig) /* only if registered */
01110          {       
01111             context->slavelist[slave].PO2SOconfig(slave);         
01112          }
01113          ecx_FPWRw(context->port, configadr, ECT_REG_ALCTL, htoes(EC_STATE_SAFE_OP) , timeout); /* set safeop status */
01114          state = ecx_statecheck(context, slave, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE); /* check state change safe-op */
01115          /* program configured FMMU */
01116          for( FMMUc = 0 ; FMMUc < context->slavelist[slave].FMMUunused ; FMMUc++ )
01117          {   
01118             ecx_FPWR(context->port, configadr, ECT_REG_FMMU0 + (sizeof(ec_fmmut) * FMMUc),
01119                sizeof(ec_fmmut), &context->slavelist[slave].FMMU[FMMUc], timeout);
01120          }
01121       }
01122    }
01123 
01124    return state;      
01125 }
01126 
01127 #ifdef EC_VER1
01128 int ec_config_init(uint8 usetable)
01129 {
01130    return ecx_config_init(&ecx_context, usetable);
01131 }
01132 
01133 int ec_config_map_group(void *pIOmap, uint8 group)
01134 {
01135    return ecx_config_map_group(&ecx_context, pIOmap, group);
01136 }
01137 
01143 int ec_config_map(void *pIOmap)
01144 {
01145    return ec_config_map_group(pIOmap, 0);
01146 }
01147 
01154 int ec_config(uint8 usetable, void *pIOmap)
01155 {
01156    int wkc;
01157    wkc = ec_config_init(usetable);
01158    if (wkc)
01159    {   
01160       ec_config_map(pIOmap);
01161    }
01162    return wkc;
01163 }
01164 
01165 int ec_recover_slave(uint16 slave, int timeout)
01166 {
01167    return ecx_recover_slave(&ecx_context, slave, timeout);
01168 }
01169 
01170 int ec_reconfig_slave(uint16 slave, int timeout)
01171 {
01172    return ecx_reconfig_slave(&ecx_context, slave, timeout);
01173 }
01174 #endif


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