drivers/ec_master.c
changeset 54 7506e67dd122
parent 53 6b3b8acb71b5
child 55 059a9e712aa7
equal deleted inserted replaced
53:6b3b8acb71b5 54:7506e67dd122
     1 /******************************************************************************
       
     2  *
       
     3  *  e c _ m a s t e r . c
       
     4  *
       
     5  *  Methoden für einen EtherCAT-Master.
       
     6  *
       
     7  *  $Id$
       
     8  *
       
     9  *****************************************************************************/
       
    10 
       
    11 #include <linux/module.h>
       
    12 #include <linux/kernel.h>
       
    13 #include <linux/string.h>
       
    14 #include <linux/slab.h>
       
    15 #include <linux/delay.h>
       
    16 
       
    17 #include "ec_globals.h"
       
    18 #include "ec_master.h"
       
    19 
       
    20 /*****************************************************************************/
       
    21 
       
    22 /**
       
    23    Konstruktor des EtherCAT-Masters.
       
    24 
       
    25    @param master Zeiger auf den zu initialisierenden EtherCAT-Master
       
    26 */
       
    27 
       
    28 void EtherCAT_master_init(EtherCAT_master_t *master)
       
    29 {
       
    30   master->bus_slaves = NULL;
       
    31   master->bus_slaves_count = 0;
       
    32   master->dev = NULL;
       
    33   master->command_index = 0x00;
       
    34   master->tx_data_length = 0;
       
    35   master->rx_data_length = 0;
       
    36   master->domain_count = 0;
       
    37   master->debug_level = 0;
       
    38   master->bus_time = 0;
       
    39   master->frames_lost = 0;
       
    40   master->t_lost_output = 0;
       
    41 }
       
    42 
       
    43 /*****************************************************************************/
       
    44 
       
    45 /**
       
    46    Destruktor eines EtherCAT-Masters.
       
    47 
       
    48    Entfernt alle Kommandos aus der Liste, löscht den Zeiger
       
    49    auf das Slave-Array und gibt die Prozessdaten frei.
       
    50 
       
    51    @param master Zeiger auf den zu löschenden Master
       
    52 */
       
    53 
       
    54 void EtherCAT_master_clear(EtherCAT_master_t *master)
       
    55 {
       
    56   if (master->bus_slaves) {
       
    57     kfree(master->bus_slaves);
       
    58     master->bus_slaves = NULL;
       
    59   }
       
    60 
       
    61   master->domain_count = 0;
       
    62 }
       
    63 
       
    64 /*****************************************************************************/
       
    65 
       
    66 /**
       
    67    Öffnet ein EtherCAT-Geraet für den Master.
       
    68 
       
    69    Registriert das Geraet beim Master, der es daraufhin oeffnet.
       
    70 
       
    71    @param master Der EtherCAT-Master
       
    72    @param device Das EtherCAT-Geraet
       
    73    @return 0, wenn alles o.k.,
       
    74    < 0, wenn bereits ein Geraet registriert
       
    75    oder das Geraet nicht geoeffnet werden konnte.
       
    76 */
       
    77 
       
    78 int EtherCAT_master_open(EtherCAT_master_t *master,
       
    79                          EtherCAT_device_t *device)
       
    80 {
       
    81   if (!master || !device) {
       
    82     printk(KERN_ERR "EtherCAT: Illegal parameters for master_open()!\n");
       
    83     return -1;
       
    84   }
       
    85 
       
    86   if (master->dev) {
       
    87     printk(KERN_ERR "EtherCAT: Master already has a device.\n");
       
    88     return -1;
       
    89   }
       
    90 
       
    91   if (EtherCAT_device_open(device) < 0) {
       
    92     printk(KERN_ERR "EtherCAT: Could not open device %X!\n",
       
    93            (unsigned int) master->dev);
       
    94     return -1;
       
    95   }
       
    96 
       
    97   master->dev = device;
       
    98 
       
    99   return 0;
       
   100 }
       
   101 
       
   102 /*****************************************************************************/
       
   103 
       
   104 /**
       
   105    Schliesst das EtherCAT-Geraet, auf dem der Master arbeitet.
       
   106 
       
   107    @param master Der EtherCAT-Master
       
   108    @param device Das EtherCAT-Geraet
       
   109 */
       
   110 
       
   111 void EtherCAT_master_close(EtherCAT_master_t *master,
       
   112                            EtherCAT_device_t *device)
       
   113 {
       
   114   if (master->dev != device) {
       
   115     printk(KERN_WARNING "EtherCAT: Warning -"
       
   116            " Trying to close an unknown device!\n");
       
   117     return;
       
   118   }
       
   119 
       
   120   if (EtherCAT_device_close(master->dev) < 0) {
       
   121     printk(KERN_WARNING "EtherCAT: Warning -"
       
   122            " Could not close device!\n");
       
   123   }
       
   124 
       
   125   master->dev = NULL;
       
   126 }
       
   127 
       
   128 /*****************************************************************************/
       
   129 
       
   130 /**
       
   131    Sendet ein einzelnes Kommando in einem Frame und
       
   132    wartet auf dessen Empfang.
       
   133 
       
   134    @param master EtherCAT-Master
       
   135    @param cmd    Kommando zum Senden/Empfangen
       
   136 
       
   137    @return 0 bei Erfolg, sonst < 0
       
   138 */
       
   139 
       
   140 int EtherCAT_simple_send_receive(EtherCAT_master_t *master,
       
   141                                  EtherCAT_command_t *cmd)
       
   142 {
       
   143   unsigned int tries_left;
       
   144 
       
   145   if (unlikely(EtherCAT_simple_send(master, cmd) < 0))
       
   146     return -1;
       
   147 
       
   148   udelay(3);
       
   149 
       
   150   EtherCAT_device_call_isr(master->dev);
       
   151 
       
   152   tries_left = 20;
       
   153   while (unlikely(master->dev->state == ECAT_DS_SENT
       
   154                   && tries_left)) {
       
   155     udelay(1);
       
   156     EtherCAT_device_call_isr(master->dev);
       
   157     tries_left--;
       
   158   }
       
   159 
       
   160   if (unlikely(EtherCAT_simple_receive(master, cmd) < 0))
       
   161     return -1;
       
   162 
       
   163   return 0;
       
   164 }
       
   165 
       
   166 /*****************************************************************************/
       
   167 
       
   168 /**
       
   169    Sendet ein einzelnes Kommando in einem Frame.
       
   170 
       
   171    @param master EtherCAT-Master
       
   172    @param cmd    Kommando zum Senden
       
   173 
       
   174    @return 0 bei Erfolg, sonst < 0
       
   175 */
       
   176 
       
   177 int EtherCAT_simple_send(EtherCAT_master_t *master,
       
   178                          EtherCAT_command_t *cmd)
       
   179 {
       
   180   unsigned int length, framelength, i;
       
   181 
       
   182   if (unlikely(master->debug_level > 0)) {
       
   183     printk(KERN_DEBUG "EtherCAT_send_receive_command\n");
       
   184   }
       
   185 
       
   186   if (unlikely(cmd->state != ECAT_CS_READY)) {
       
   187     printk(KERN_WARNING "EtherCAT_send_receive_command:"
       
   188            "Command not in ready state!\n");
       
   189   }
       
   190 
       
   191   length = cmd->data_length + 12;
       
   192   framelength = length + 2;
       
   193 
       
   194   if (unlikely(framelength > ECAT_FRAME_BUFFER_SIZE)) {
       
   195     printk(KERN_ERR "EtherCAT: Frame too long (%i)!\n", framelength);
       
   196     return -1;
       
   197   }
       
   198 
       
   199   if (framelength < 46) framelength = 46;
       
   200 
       
   201   if (unlikely(master->debug_level > 0)) {
       
   202     printk(KERN_DEBUG "Frame length: %i\n", framelength);
       
   203   }
       
   204 
       
   205   master->tx_data[0] = length & 0xFF;
       
   206   master->tx_data[1] = ((length & 0x700) >> 8) | 0x10;
       
   207 
       
   208   cmd->index = master->command_index;
       
   209   master->command_index = (master->command_index + 1) % 0x0100;
       
   210 
       
   211   if (unlikely(master->debug_level > 0)) {
       
   212     printk(KERN_DEBUG "Sending command index %i\n", cmd->index);
       
   213   }
       
   214 
       
   215   cmd->state = ECAT_CS_SENT;
       
   216 
       
   217   master->tx_data[2 + 0] = cmd->type;
       
   218   master->tx_data[2 + 1] = cmd->index;
       
   219   master->tx_data[2 + 2] = cmd->address.raw[0];
       
   220   master->tx_data[2 + 3] = cmd->address.raw[1];
       
   221   master->tx_data[2 + 4] = cmd->address.raw[2];
       
   222   master->tx_data[2 + 5] = cmd->address.raw[3];
       
   223   master->tx_data[2 + 6] = cmd->data_length & 0xFF;
       
   224   master->tx_data[2 + 7] = (cmd->data_length & 0x700) >> 8;
       
   225   master->tx_data[2 + 8] = 0x00;
       
   226   master->tx_data[2 + 9] = 0x00;
       
   227 
       
   228   if (likely(cmd->type == ECAT_CMD_APWR
       
   229              || cmd->type == ECAT_CMD_NPWR
       
   230              || cmd->type == ECAT_CMD_BWR
       
   231              || cmd->type == ECAT_CMD_LRW)) // Write commands
       
   232   {
       
   233     for (i = 0; i < cmd->data_length; i++)
       
   234       master->tx_data[2 + 10 + i] = cmd->data[i];
       
   235   }
       
   236   else // Read commands
       
   237   {
       
   238     for (i = 0; i < cmd->data_length; i++) master->tx_data[2 + 10 + i] = 0x00;
       
   239   }
       
   240 
       
   241   master->tx_data[2 + 10 + cmd->data_length] = 0x00;
       
   242   master->tx_data[2 + 11 + cmd->data_length] = 0x00;
       
   243 
       
   244   // Pad with zeros
       
   245   for (i = cmd->data_length + 12 + 2; i < 46; i++) master->tx_data[i] = 0x00;
       
   246 
       
   247   master->tx_data_length = framelength;
       
   248 
       
   249   if (unlikely(master->debug_level > 0)) {
       
   250     printk(KERN_DEBUG "device send...\n");
       
   251   }
       
   252 
       
   253   // Send frame
       
   254   if (unlikely(EtherCAT_device_send(master->dev,
       
   255                                     master->tx_data,
       
   256                                     framelength) != 0)) {
       
   257     printk(KERN_ERR "EtherCAT: Could not send!\n");
       
   258     return -1;
       
   259   }
       
   260 
       
   261   if (unlikely(master->debug_level > 0)) {
       
   262     printk(KERN_DEBUG "EtherCAT_send done.\n");
       
   263   }
       
   264 
       
   265   return 0;
       
   266 }
       
   267 
       
   268 /*****************************************************************************/
       
   269 
       
   270 /**
       
   271    Wartet auf den Empfang eines einzeln gesendeten
       
   272    Kommandos.
       
   273 
       
   274    @param master EtherCAT-Master
       
   275    @param cmd    Gesendetes Kommando
       
   276 
       
   277    @return 0 bei Erfolg, sonst < 0
       
   278 */
       
   279 
       
   280 int EtherCAT_simple_receive(EtherCAT_master_t *master,
       
   281                             EtherCAT_command_t *cmd)
       
   282 {
       
   283   unsigned int length;
       
   284   int ret;
       
   285   unsigned char command_type, command_index;
       
   286 
       
   287   if (unlikely((ret = EtherCAT_device_receive(master->dev,
       
   288                                               master->rx_data)) < 0))
       
   289     return -1;
       
   290 
       
   291   master->rx_data_length = (unsigned int) ret;
       
   292 
       
   293   if (unlikely(master->rx_data_length < 2)) {
       
   294     printk(KERN_ERR "EtherCAT: Received frame with incomplete EtherCAT"
       
   295            " header!\n");
       
   296     output_debug_data(master);
       
   297     return -1;
       
   298   }
       
   299 
       
   300   // Länge des gesamten Frames prüfen
       
   301   length = ((master->rx_data[1] & 0x07) << 8)
       
   302     | (master->rx_data[0] & 0xFF);
       
   303 
       
   304   if (unlikely(length > master->rx_data_length)) {
       
   305     printk(KERN_ERR "EtherCAT: Received corrupted frame (length does"
       
   306            " not match)!\n");
       
   307     output_debug_data(master);
       
   308     return -1;
       
   309   }
       
   310 
       
   311   command_type = master->rx_data[2];
       
   312   command_index = master->rx_data[2 + 1];
       
   313   length = (master->rx_data[2 + 6] & 0xFF)
       
   314     | ((master->rx_data[2 + 7] & 0x07) << 8);
       
   315 
       
   316   if (unlikely(master->rx_data_length - 2 < length + 12)) {
       
   317     printk(KERN_ERR "EtherCAT: Received frame with"
       
   318            " incomplete command data!\n");
       
   319     output_debug_data(master);
       
   320     return -1;
       
   321   }
       
   322 
       
   323   if (likely(cmd->state == ECAT_CS_SENT
       
   324              && cmd->type == command_type
       
   325              && cmd->index == command_index
       
   326              && cmd->data_length == length))
       
   327   {
       
   328     cmd->state = ECAT_CS_RECEIVED;
       
   329 
       
   330     // Empfangene Daten in Kommandodatenspeicher kopieren
       
   331     memcpy(cmd->data, master->rx_data + 2 + 10, length);
       
   332 
       
   333     // Working-Counter setzen
       
   334     cmd->working_counter
       
   335       = ((master->rx_data[length + 2 + 10] & 0xFF)
       
   336          | ((master->rx_data[length + 2 + 11] & 0xFF) << 8));
       
   337 
       
   338     if (unlikely(master->debug_level > 1)) {
       
   339       output_debug_data(master);
       
   340     }
       
   341   }
       
   342   else
       
   343   {
       
   344     printk(KERN_WARNING "EtherCAT: WARNING - Send/Receive anomaly!\n");
       
   345     output_debug_data(master);
       
   346   }
       
   347 
       
   348   master->dev->state = ECAT_DS_READY;
       
   349 
       
   350   return 0;
       
   351 }
       
   352 
       
   353 /*****************************************************************************/
       
   354 
       
   355 /**
       
   356    Durchsucht den Bus nach Slaves.
       
   357 
       
   358    @param master Der EtherCAT-Master
       
   359 
       
   360    @return 0 bei Erfolg, sonst < 0
       
   361 */
       
   362 
       
   363 int EtherCAT_scan_for_slaves(EtherCAT_master_t *master)
       
   364 {
       
   365   EtherCAT_command_t cmd;
       
   366   EtherCAT_slave_t *cur;
       
   367   unsigned int i, j;
       
   368   unsigned char data[2];
       
   369 
       
   370   // Determine number of slaves on bus
       
   371 
       
   372   EtherCAT_command_broadcast_read(&cmd, 0x0000, 4);
       
   373 
       
   374   if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
       
   375     return -1;
       
   376 
       
   377   master->bus_slaves_count = cmd.working_counter;
       
   378   printk("EtherCAT: Found %i slaves on bus.\n", master->bus_slaves_count);
       
   379 
       
   380   if (!master->bus_slaves_count) return 0;
       
   381 
       
   382   if (!(master->bus_slaves =
       
   383         (EtherCAT_slave_t *) kmalloc(master->bus_slaves_count *
       
   384                                      sizeof(EtherCAT_slave_t), GFP_KERNEL))) {
       
   385     printk(KERN_ERR "EtherCAT: Could not allocate memory for bus slaves!\n");
       
   386     return -1;
       
   387   }
       
   388 
       
   389   // For every slave in the list
       
   390   for (i = 0; i < master->bus_slaves_count; i++)
       
   391   {
       
   392     cur = master->bus_slaves + i;
       
   393 
       
   394     EtherCAT_slave_init(cur);
       
   395 
       
   396     // Read base data
       
   397 
       
   398     EtherCAT_command_read(&cmd, cur->station_address, 0x0000, 4);
       
   399 
       
   400     if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
       
   401       return -1;
       
   402 
       
   403     if (unlikely(cmd.working_counter != 1)) {
       
   404       printk(KERN_ERR "EtherCAT: Slave %i did not respond"
       
   405              " while reading base data!\n", i);
       
   406       return -1;
       
   407     }
       
   408 
       
   409     // Get base data
       
   410 
       
   411     cur->type = cmd.data[0];
       
   412     cur->revision = cmd.data[1];
       
   413     cur->build = cmd.data[2] | (cmd.data[3] << 8);
       
   414 
       
   415     // Read identification from "Slave Information Interface" (SII)
       
   416 
       
   417     if (unlikely(EtherCAT_read_slave_information(master,
       
   418                                                  cur->station_address,
       
   419                                                  0x0008,
       
   420                                                  &cur->vendor_id) != 0))
       
   421     {
       
   422       printk(KERN_ERR "EtherCAT: Could not read SII vendor id!\n");
       
   423       return -1;
       
   424     }
       
   425 
       
   426     if (unlikely(EtherCAT_read_slave_information(master,
       
   427                                                  cur->station_address,
       
   428                                                  0x000A,
       
   429                                                  &cur->product_code) != 0))
       
   430     {
       
   431       printk(KERN_ERR "EtherCAT: Could not read SII product code!\n");
       
   432       return -1;
       
   433     }
       
   434 
       
   435     if (unlikely(EtherCAT_read_slave_information(master,
       
   436                                                  cur->station_address,
       
   437                                                  0x000C,
       
   438                                                  &cur->revision_number) != 0))
       
   439     {
       
   440       printk(KERN_ERR "EtherCAT: Could not read SII revision number!\n");
       
   441       return -1;
       
   442     }
       
   443 
       
   444     if (unlikely(EtherCAT_read_slave_information(master,
       
   445                                                  cur->station_address,
       
   446                                                  0x000E,
       
   447                                                  &cur->serial_number) != 0))
       
   448     {
       
   449       printk(KERN_ERR "EtherCAT: Could not read SII serial number!\n");
       
   450       return -1;
       
   451     }
       
   452 
       
   453     // Search for identification in "database"
       
   454 
       
   455     for (j = 0; j < slave_ident_count; j++)
       
   456     {
       
   457       if (unlikely(slave_idents[j].vendor_id == cur->vendor_id
       
   458                    && slave_idents[j].product_code == cur->product_code))
       
   459       {
       
   460         cur->desc = slave_idents[j].desc;
       
   461         break;
       
   462       }
       
   463     }
       
   464 
       
   465     if (unlikely(!cur->desc)) {
       
   466       printk(KERN_ERR "EtherCAT: Unknown slave device (vendor %X, code %X) at "
       
   467              " position %i.\n", cur->vendor_id, cur->product_code, i);
       
   468       return -1;
       
   469     }
       
   470 
       
   471     // Set ring position
       
   472     cur->ring_position = -i;
       
   473     cur->station_address = i + 1;
       
   474 
       
   475     // Write station address
       
   476 
       
   477     data[0] = cur->station_address & 0x00FF;
       
   478     data[1] = (cur->station_address & 0xFF00) >> 8;
       
   479 
       
   480     EtherCAT_command_position_write(&cmd, cur->ring_position,
       
   481                                     0x0010, 2, data);
       
   482 
       
   483     if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
       
   484       return -1;
       
   485 
       
   486     if (unlikely(cmd.working_counter != 1)) {
       
   487       printk(KERN_ERR "EtherCAT: Slave %i did not repond"
       
   488              " while writing station address!\n", i);
       
   489       return -1;
       
   490     }
       
   491   }
       
   492 
       
   493   return 0;
       
   494 }
       
   495 
       
   496 /*****************************************************************************/
       
   497 
       
   498 /**
       
   499    Registriert einen Slave beim Master.
       
   500 
       
   501    @param master Der EtherCAT-Master
       
   502 
       
   503    @return 0 bei Erfolg, sonst < 0
       
   504 */
       
   505 
       
   506 void *EtherCAT_register_slave(EtherCAT_master_t *master,
       
   507                               unsigned int bus_index,
       
   508                               const char *vendor_name,
       
   509                               const char *product_name,
       
   510                               unsigned int domain)
       
   511 {
       
   512   EtherCAT_slave_t *slave;
       
   513   EtherCAT_domain_t *dom;
       
   514   unsigned int j;
       
   515 
       
   516   if (bus_index >= master->bus_slaves_count) {
       
   517     printk(KERN_ERR "EtherCAT: Illegal bus index! (%i / %i)\n", bus_index,
       
   518            master->bus_slaves_count);
       
   519     return NULL;
       
   520   }
       
   521 
       
   522   slave = master->bus_slaves + bus_index;
       
   523 
       
   524   if (slave->process_data) {
       
   525     printk(KERN_ERR "EtherCAT: Slave %i is already registered!\n", bus_index);
       
   526     return NULL;
       
   527   }
       
   528 
       
   529   if (strcmp(vendor_name, slave->desc->vendor_name) ||
       
   530       strcmp(product_name, slave->desc->product_name)) {
       
   531     printk(KERN_ERR "Invalid Slave Type! Requested: \"%s %s\", present: \"%s"
       
   532            "%s\".\n", vendor_name, product_name, slave->desc->vendor_name,
       
   533            slave->desc->product_name);
       
   534     return NULL;
       
   535   }
       
   536 
       
   537   // Check, if process data domain already exists...
       
   538   dom = NULL;
       
   539   for (j = 0; j < master->domain_count; j++) {
       
   540     if (domain == master->domains[j].number) {
       
   541       dom = master->domains + j;
       
   542     }
       
   543   }
       
   544 
       
   545   // Create process data domain
       
   546   if (!dom) {
       
   547     if (master->domain_count > ECAT_MAX_DOMAINS - 1) {
       
   548       printk(KERN_ERR "EtherCAT: Too many domains!\n");
       
   549       return NULL;
       
   550     }
       
   551 
       
   552     dom = master->domains + master->domain_count;
       
   553     EtherCAT_domain_init(dom);
       
   554     dom->number = domain;
       
   555     dom->logical_offset = master->domain_count * ECAT_FRAME_BUFFER_SIZE;
       
   556     master->domain_count++;
       
   557   }
       
   558 
       
   559   if (dom->data_size + slave->desc->process_data_size
       
   560       > ECAT_FRAME_BUFFER_SIZE - 14) {
       
   561     printk(KERN_ERR "EtherCAT: Oversized domain %i: %i / %i Bytes!\n",
       
   562            dom->number, dom->data_size + slave->desc->process_data_size,
       
   563            ECAT_FRAME_BUFFER_SIZE - 14);
       
   564     return NULL;
       
   565   }
       
   566 
       
   567   slave->process_data = dom->data + dom->data_size;
       
   568   dom->data_size += slave->desc->process_data_size;
       
   569 
       
   570   return slave->process_data;
       
   571 }
       
   572 
       
   573 /*****************************************************************************/
       
   574 
       
   575 /**
       
   576    Liest Daten aus dem Slave-Information-Interface
       
   577    eines EtherCAT-Slaves.
       
   578 
       
   579    @param master EtherCAT-Master
       
   580    @param node_address Knotenadresse des Slaves
       
   581    @param offset Adresse des zu lesenden SII-Registers
       
   582    @param target Zeiger auf einen 4 Byte großen Speicher
       
   583    zum Ablegen der Daten
       
   584 
       
   585    @return 0 bei Erfolg, sonst < 0
       
   586 */
       
   587 
       
   588 int EtherCAT_read_slave_information(EtherCAT_master_t *master,
       
   589                                     unsigned short int node_address,
       
   590                                     unsigned short int offset,
       
   591                                     unsigned int *target)
       
   592 {
       
   593   EtherCAT_command_t cmd;
       
   594   unsigned char data[10];
       
   595   unsigned int tries_left;
       
   596 
       
   597   // Initiate read operation
       
   598 
       
   599   data[0] = 0x00;
       
   600   data[1] = 0x01;
       
   601   data[2] = offset & 0xFF;
       
   602   data[3] = (offset & 0xFF00) >> 8;
       
   603   data[4] = 0x00;
       
   604   data[5] = 0x00;
       
   605 
       
   606   EtherCAT_command_write(&cmd, node_address, 0x502, 6, data);
       
   607 
       
   608   if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
       
   609     return -1;
       
   610 
       
   611   if (unlikely(cmd.working_counter != 1)) {
       
   612     printk(KERN_ERR "EtherCAT: SII-read - Slave %04X did not respond!\n",
       
   613            node_address);
       
   614     return -1;
       
   615   }
       
   616 
       
   617   // Der Slave legt die Informationen des Slave-Information-Interface
       
   618   // in das Datenregister und löscht daraufhin ein Busy-Bit. Solange
       
   619   // den Status auslesen, bis das Bit weg ist.
       
   620 
       
   621   tries_left = 100;
       
   622   while (likely(tries_left))
       
   623   {
       
   624     udelay(10);
       
   625 
       
   626     EtherCAT_command_read(&cmd, node_address, 0x502, 10);
       
   627 
       
   628     if (unlikely(EtherCAT_simple_send_receive(master, &cmd) != 0))
       
   629       return -1;
       
   630 
       
   631     if (unlikely(cmd.working_counter != 1)) {
       
   632       printk(KERN_ERR "EtherCAT: SII-read status -"
       
   633              " Slave %04X did not respond!\n", node_address);
       
   634       return -1;
       
   635     }
       
   636 
       
   637     if (likely((cmd.data[1] & 0x81) == 0)) {
       
   638       memcpy(target, cmd.data + 6, 4);
       
   639       break;
       
   640     }
       
   641 
       
   642     tries_left--;
       
   643   }
       
   644 
       
   645   if (unlikely(!tries_left)) {
       
   646     printk(KERN_WARNING "EtherCAT: SSI-read. Slave %04X timed out!\n",
       
   647            node_address);
       
   648     return -1;
       
   649   }
       
   650 
       
   651   return 0;
       
   652 }
       
   653 
       
   654 /*****************************************************************************/
       
   655 
       
   656 /**
       
   657    Ändert den Zustand eines Slaves (asynchron).
       
   658 
       
   659    Führt eine (asynchrone) Zustandsänderung bei einem Slave durch.
       
   660 
       
   661    @param master EtherCAT-Master
       
   662    @param slave Slave, dessen Zustand geändert werden soll
       
   663    @param state_and_ack Neuer Zustand, evtl. mit gesetztem
       
   664    Acknowledge-Flag
       
   665 
       
   666    @return 0 bei Erfolg, sonst < 0
       
   667 */
       
   668 
       
   669 int EtherCAT_state_change(EtherCAT_master_t *master,
       
   670                           EtherCAT_slave_t *slave,
       
   671                           unsigned char state_and_ack)
       
   672 {
       
   673   EtherCAT_command_t cmd;
       
   674   unsigned char data[2];
       
   675   unsigned int tries_left;
       
   676 
       
   677   data[0] = state_and_ack;
       
   678   data[1] = 0x00;
       
   679 
       
   680   EtherCAT_command_write(&cmd, slave->station_address,
       
   681                          0x0120, 2, data);
       
   682 
       
   683   if (unlikely(EtherCAT_simple_send_receive(master, &cmd) != 0)) {
       
   684     printk(KERN_ERR "EtherCAT: Could not set state %02X - Unable to send!\n",
       
   685            state_and_ack);
       
   686     return -1;
       
   687   }
       
   688 
       
   689   if (unlikely(cmd.working_counter != 1)) {
       
   690     printk(KERN_ERR "EtherCAT: Could not set state %02X - Device \"%s %s\""
       
   691            " (%d) did not respond!\n", state_and_ack, slave->desc->vendor_name,
       
   692            slave->desc->product_name, slave->ring_position * (-1));
       
   693     return -1;
       
   694   }
       
   695 
       
   696   slave->requested_state = state_and_ack & 0x0F;
       
   697 
       
   698   tries_left = 100;
       
   699   while (likely(tries_left))
       
   700   {
       
   701     udelay(10);
       
   702 
       
   703     EtherCAT_command_read(&cmd, slave->station_address, 0x0130, 2);
       
   704 
       
   705     if (unlikely(EtherCAT_simple_send_receive(master, &cmd) != 0)) {
       
   706       printk(KERN_ERR "EtherCAT: Could not check state %02X - Unable to"
       
   707              " send!\n", state_and_ack);
       
   708       return -1;
       
   709     }
       
   710 
       
   711     if (unlikely(cmd.working_counter != 1)) {
       
   712       printk(KERN_ERR "EtherCAT: Could not check state %02X - Device did not"
       
   713              " respond!\n", state_and_ack);
       
   714       return -1;
       
   715     }
       
   716 
       
   717     if (unlikely(cmd.data[0] & 0x10)) { // State change error
       
   718       printk(KERN_ERR "EtherCAT: Could not set state %02X - Device refused"
       
   719              " state change (code %02X)!\n", state_and_ack, cmd.data[0]);
       
   720       return -1;
       
   721     }
       
   722 
       
   723     if (likely(cmd.data[0] == (state_and_ack & 0x0F))) {
       
   724       // State change successful
       
   725       break;
       
   726     }
       
   727 
       
   728     tries_left--;
       
   729   }
       
   730 
       
   731   if (unlikely(!tries_left)) {
       
   732     printk(KERN_ERR "EtherCAT: Could not check state %02X - Timeout while"
       
   733            " checking!\n", state_and_ack);
       
   734     return -1;
       
   735   }
       
   736 
       
   737   slave->current_state = state_and_ack & 0x0F;
       
   738 
       
   739   return 0;
       
   740 }
       
   741 
       
   742 /*****************************************************************************/
       
   743 
       
   744 /**
       
   745    Konfiguriert einen Slave und setzt den Operational-Zustand.
       
   746 
       
   747    Führt eine komplette Konfiguration eines Slaves durch,
       
   748    setzt Sync-Manager und FMMU's, führt die entsprechenden
       
   749    Zustandsübergänge durch, bis der Slave betriebsbereit ist.
       
   750 
       
   751    @param master EtherCAT-Master
       
   752    @param slave Zu aktivierender Slave
       
   753 
       
   754    @return 0 bei Erfolg, sonst < 0
       
   755 */
       
   756 
       
   757 int EtherCAT_activate_slave(EtherCAT_master_t *master,
       
   758                             EtherCAT_slave_t *slave)
       
   759 {
       
   760   EtherCAT_command_t cmd;
       
   761   const EtherCAT_slave_desc_t *desc;
       
   762   unsigned char fmmu[16];
       
   763   unsigned char data[256];
       
   764 
       
   765   desc = slave->desc;
       
   766 
       
   767   if (unlikely(EtherCAT_state_change(master, slave, ECAT_STATE_INIT) != 0))
       
   768     return -1;
       
   769 
       
   770   // Resetting FMMU's
       
   771 
       
   772   memset(data, 0x00, 256);
       
   773 
       
   774   EtherCAT_command_write(&cmd, slave->station_address, 0x0600, 256, data);
       
   775 
       
   776   if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
       
   777     return -1;
       
   778 
       
   779   if (unlikely(cmd.working_counter != 1)) {
       
   780     printk(KERN_ERR "EtherCAT: Resetting FMMUs - Slave %04X did not"
       
   781            " respond!\n", slave->station_address);
       
   782     return -1;
       
   783   }
       
   784 
       
   785   // Resetting Sync Manager channels
       
   786 
       
   787   if (desc->type != ECAT_ST_SIMPLE_NOSYNC)
       
   788   {
       
   789     memset(data, 0x00, 256);
       
   790 
       
   791     EtherCAT_command_write(&cmd, slave->station_address, 0x0800, 256, data);
       
   792 
       
   793     if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
       
   794       return -1;
       
   795 
       
   796     if (unlikely(cmd.working_counter != 1)) {
       
   797       printk(KERN_ERR "EtherCAT: Resetting SMs - Slave %04X did not"
       
   798              " respond!\n", slave->station_address);
       
   799       return -1;
       
   800     }
       
   801   }
       
   802 
       
   803   // Init Mailbox communication
       
   804 
       
   805   if (desc->type == ECAT_ST_MAILBOX)
       
   806   {
       
   807     if (desc->sm0)
       
   808     {
       
   809       EtherCAT_command_write(&cmd, slave->station_address, 0x0800, 8,
       
   810                              desc->sm0);
       
   811 
       
   812       if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
       
   813         return -1;
       
   814 
       
   815       if (unlikely(cmd.working_counter != 1)) {
       
   816         printk(KERN_ERR "EtherCAT: Setting SM0 - Slave %04X did not"
       
   817                " respond!\n", slave->station_address);
       
   818         return -1;
       
   819       }
       
   820     }
       
   821 
       
   822     if (desc->sm1)
       
   823     {
       
   824       EtherCAT_command_write(&cmd, slave->station_address, 0x0808, 8,
       
   825                              desc->sm1);
       
   826 
       
   827       if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
       
   828         return -1;
       
   829 
       
   830       if (unlikely(cmd.working_counter != 1)) {
       
   831         printk(KERN_ERR "EtherCAT: Setting SM1 -"
       
   832                " Slave %04X did not respond!\n",
       
   833                slave->station_address);
       
   834         return -1;
       
   835       }
       
   836     }
       
   837   }
       
   838 
       
   839   // Change state to PREOP
       
   840 
       
   841   if (unlikely(EtherCAT_state_change(master, slave, ECAT_STATE_PREOP) != 0))
       
   842     return -1;
       
   843 
       
   844   // Set FMMU's
       
   845 
       
   846   if (desc->fmmu0)
       
   847   {
       
   848     if (unlikely(!slave->process_data)) {
       
   849       printk(KERN_ERR "EtherCAT: Warning - Slave %04X is not assigned to any"
       
   850              " process data object!\n", slave->station_address);
       
   851       return -1;
       
   852     }
       
   853 
       
   854     memcpy(fmmu, desc->fmmu0, 16);
       
   855 
       
   856     fmmu[0] = slave->logical_address & 0x000000FF;
       
   857     fmmu[1] = (slave->logical_address & 0x0000FF00) >> 8;
       
   858     fmmu[2] = (slave->logical_address & 0x00FF0000) >> 16;
       
   859     fmmu[3] = (slave->logical_address & 0xFF000000) >> 24;
       
   860 
       
   861     EtherCAT_command_write(&cmd, slave->station_address, 0x0600, 16, fmmu);
       
   862 
       
   863     if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
       
   864       return -1;
       
   865 
       
   866     if (unlikely(cmd.working_counter != 1)) {
       
   867       printk(KERN_ERR "EtherCAT: Setting FMMU0 - Slave %04X did not"
       
   868              " respond!\n", slave->station_address);
       
   869       return -1;
       
   870     }
       
   871   }
       
   872 
       
   873   // Set Sync Managers
       
   874 
       
   875   if (desc->type != ECAT_ST_MAILBOX)
       
   876   {
       
   877     if (desc->sm0)
       
   878     {
       
   879       EtherCAT_command_write(&cmd, slave->station_address, 0x0800, 8,
       
   880                              desc->sm0);
       
   881 
       
   882       if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
       
   883         return -1;
       
   884 
       
   885       if (unlikely(cmd.working_counter != 1)) {
       
   886         printk(KERN_ERR "EtherCAT: Setting SM0 - Slave %04X did not"
       
   887                " respond!\n", slave->station_address);
       
   888         return -1;
       
   889       }
       
   890     }
       
   891 
       
   892     if (desc->sm1)
       
   893     {
       
   894       EtherCAT_command_write(&cmd, slave->station_address, 0x0808, 8,
       
   895                              desc->sm1);
       
   896 
       
   897       if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
       
   898         return -1;
       
   899 
       
   900       if (unlikely(cmd.working_counter != 1)) {
       
   901         printk(KERN_ERR "EtherCAT: Setting SM1 - Slave %04X did not"
       
   902                " respond!\n", slave->station_address);
       
   903         return -1;
       
   904       }
       
   905     }
       
   906   }
       
   907 
       
   908   if (desc->sm2)
       
   909   {
       
   910     EtherCAT_command_write(&cmd, slave->station_address, 0x0810, 8, desc->sm2);
       
   911 
       
   912     if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
       
   913       return -1;
       
   914 
       
   915     if (unlikely(cmd.working_counter != 1)) {
       
   916       printk(KERN_ERR "EtherCAT: Setting SM2 - Slave %04X did not respond!\n",
       
   917              slave->station_address);
       
   918       return -1;
       
   919     }
       
   920   }
       
   921 
       
   922   if (desc->sm3)
       
   923   {
       
   924     EtherCAT_command_write(&cmd, slave->station_address, 0x0818, 8, desc->sm3);
       
   925 
       
   926     if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0))
       
   927       return -1;
       
   928 
       
   929     if (unlikely(cmd.working_counter != 1)) {
       
   930       printk(KERN_ERR "EtherCAT: Setting SM3 - Slave %04X did not respond!\n",
       
   931              slave->station_address);
       
   932       return -1;
       
   933     }
       
   934   }
       
   935 
       
   936   // Change state to SAVEOP
       
   937   if (unlikely(EtherCAT_state_change(master, slave, ECAT_STATE_SAVEOP) != 0))
       
   938     return -1;
       
   939 
       
   940   // Change state to OP
       
   941   if (unlikely(EtherCAT_state_change(master, slave, ECAT_STATE_OP) != 0))
       
   942     return -1;
       
   943 
       
   944   return 0;
       
   945 }
       
   946 
       
   947 /*****************************************************************************/
       
   948 
       
   949 /**
       
   950    Setzt einen Slave zurück in den Init-Zustand.
       
   951 
       
   952    @param master EtherCAT-Master
       
   953    @param slave Zu deaktivierender Slave
       
   954 
       
   955    @return 0 bei Erfolg, sonst < 0
       
   956 */
       
   957 
       
   958 int EtherCAT_deactivate_slave(EtherCAT_master_t *master,
       
   959                               EtherCAT_slave_t *slave)
       
   960 {
       
   961   if (unlikely(EtherCAT_state_change(master, slave,
       
   962                                      ECAT_STATE_INIT) != 0))
       
   963     return -1;
       
   964 
       
   965   return 0;
       
   966 }
       
   967 
       
   968 /*****************************************************************************/
       
   969 
       
   970 /**
       
   971    Sendet und empfängt Prozessdaten der angegebenen Domäne
       
   972 
       
   973    @param master     EtherCAT-Master
       
   974           domain     Domäne
       
   975           timeout_us Timeout in Mikrosekunden
       
   976 
       
   977    @return 0 bei Erfolg, sonst < 0
       
   978 */
       
   979 
       
   980 int EtherCAT_process_data_cycle(EtherCAT_master_t *master, unsigned int domain,
       
   981                                 unsigned int timeout_us)
       
   982 {
       
   983   unsigned int i;
       
   984   EtherCAT_domain_t *dom;
       
   985   unsigned long start_ticks, end_ticks, timeout_ticks;
       
   986 
       
   987   ecat_output_lost_frames(master); // Evtl. verlorene Frames ausgeben
       
   988 
       
   989   // Domäne bestimmen
       
   990   dom = NULL;
       
   991   for (i = 0; i < master->domain_count; i++) {
       
   992     if (master->domains[i].number == domain) {
       
   993       dom = master->domains + i;
       
   994       break;
       
   995     }
       
   996   }
       
   997 
       
   998   if (unlikely(!dom)) {
       
   999     printk(KERN_ERR "EtherCAT: No such domain: %i!\n", domain);
       
  1000     return -1;
       
  1001   }
       
  1002 
       
  1003   EtherCAT_command_logical_read_write(&dom->command,
       
  1004                                       dom->logical_offset, dom->data_size,
       
  1005                                       dom->data);
       
  1006 
       
  1007   rdtscl(start_ticks); // Sendezeit nehmen
       
  1008 
       
  1009   if (unlikely(EtherCAT_simple_send(master, &dom->command) < 0)) {
       
  1010     printk(KERN_ERR "EtherCAT: Could not send process data command!\n");
       
  1011     return -1;
       
  1012   }
       
  1013 
       
  1014   timeout_ticks = timeout_us * cpu_khz / 1000;
       
  1015 
       
  1016   // Warten
       
  1017   do {
       
  1018     EtherCAT_device_call_isr(master->dev);
       
  1019     rdtscl(end_ticks); // Empfangszeit nehmen
       
  1020   }
       
  1021   while (unlikely(master->dev->state == ECAT_DS_SENT
       
  1022                   && end_ticks - start_ticks < timeout_ticks));
       
  1023 
       
  1024   master->bus_time = (end_ticks - start_ticks) * 1000 / cpu_khz;
       
  1025 
       
  1026   if (unlikely(end_ticks - start_ticks >= timeout_ticks)) {
       
  1027     master->dev->state = ECAT_DS_READY;
       
  1028     master->frames_lost++;
       
  1029     ecat_output_lost_frames(master);
       
  1030     return -1;
       
  1031   }
       
  1032 
       
  1033   if (unlikely(EtherCAT_simple_receive(master, &dom->command) < 0)) {
       
  1034     printk(KERN_ERR "EtherCAT: Could not receive cyclic command!\n");
       
  1035     return -1;
       
  1036   }
       
  1037 
       
  1038   if (unlikely(dom->command.state != ECAT_CS_RECEIVED)) {
       
  1039     printk(KERN_WARNING "EtherCAT: Process data command not received!\n");
       
  1040     return -1;
       
  1041   }
       
  1042 
       
  1043   if (dom->command.working_counter != dom->response_count) {
       
  1044     dom->response_count = dom->command.working_counter;
       
  1045     printk(KERN_INFO "EtherCAT: Domain %i State change - %i slaves"
       
  1046            " responding.\n", dom->number, dom->response_count);
       
  1047   }
       
  1048 
       
  1049   // Daten vom Kommando in den Prozessdatenspeicher kopieren
       
  1050   memcpy(dom->data, dom->command.data, dom->data_size);
       
  1051 
       
  1052   return 0;
       
  1053 }
       
  1054 
       
  1055 /*****************************************************************************/
       
  1056 
       
  1057 /**
       
  1058    Gibt Frame-Inhalte zwecks Debugging aus.
       
  1059 
       
  1060    @param master EtherCAT-Master
       
  1061 */
       
  1062 
       
  1063 void output_debug_data(const EtherCAT_master_t *master)
       
  1064 {
       
  1065   unsigned int i;
       
  1066 
       
  1067   printk(KERN_DEBUG "EtherCAT: tx_data content (%i Bytes):\n",
       
  1068          master->tx_data_length);
       
  1069 
       
  1070   printk(KERN_DEBUG);
       
  1071   for (i = 0; i < master->tx_data_length; i++)
       
  1072   {
       
  1073     printk("%02X ", master->tx_data[i]);
       
  1074     if ((i + 1) % 16 == 0) printk("\n" KERN_DEBUG);
       
  1075   }
       
  1076   printk("\n");
       
  1077 
       
  1078   printk(KERN_DEBUG "EtherCAT: rx_data content (%i Bytes):\n",
       
  1079          master->rx_data_length);
       
  1080 
       
  1081   printk(KERN_DEBUG);
       
  1082   for (i = 0; i < master->rx_data_length; i++)
       
  1083   {
       
  1084     printk("%02X ", master->rx_data[i]);
       
  1085     if ((i + 1) % 16 == 0) printk("\n" KERN_DEBUG);
       
  1086   }
       
  1087   printk("\n");
       
  1088 }
       
  1089 
       
  1090 /*****************************************************************************/
       
  1091 
       
  1092 /**
       
  1093    Gibt von Zeit zu Zeit die Anzahl verlorener Frames aus.
       
  1094 
       
  1095    @param master EtherCAT-Master
       
  1096 */
       
  1097 
       
  1098 void ecat_output_lost_frames(EtherCAT_master_t *master)
       
  1099 {
       
  1100   unsigned long int t;
       
  1101 
       
  1102   if (master->frames_lost) {
       
  1103     rdtscl(t);
       
  1104     if ((t - master->t_lost_output) / cpu_khz > 1000) {
       
  1105       printk(KERN_ERR "EtherCAT: %u frame(s) LOST!\n", master->frames_lost);
       
  1106       master->frames_lost = 0;
       
  1107       master->t_lost_output = t;
       
  1108     }
       
  1109   }
       
  1110 }
       
  1111 
       
  1112 /*****************************************************************************/
       
  1113 
       
  1114 EXPORT_SYMBOL(EtherCAT_master_open);
       
  1115 EXPORT_SYMBOL(EtherCAT_master_close);
       
  1116 EXPORT_SYMBOL(EtherCAT_activate_slave);
       
  1117 EXPORT_SYMBOL(EtherCAT_deactivate_slave);
       
  1118 EXPORT_SYMBOL(EtherCAT_process_data_cycle);
       
  1119 
       
  1120 /*****************************************************************************/
       
  1121 
       
  1122 /* Emacs-Konfiguration
       
  1123 ;;; Local Variables: ***
       
  1124 ;;; c-basic-offset:2 ***
       
  1125 ;;; End: ***
       
  1126 */