master/domain.c
changeset 195 674071846ee3
parent 184 2fc86cec12df
child 197 b9a6e2c22745
child 1618 5cff10efb927
equal deleted inserted replaced
194:c21e7c12dd50 195:674071846ee3
     1 /******************************************************************************
     1 /******************************************************************************
     2  *
     2  *
     3  *  d o m a i n . c
     3  *  d o m a i n . c
     4  *
     4  *
     5  *  Methoden für Gruppen von EtherCAT-Slaves.
     5  *  EtherCAT domain methods.
     6  *
     6  *
     7  *  $Id$
     7  *  $Id$
     8  *
     8  *
     9  *****************************************************************************/
     9  *****************************************************************************/
    10 
    10 
    38 };
    38 };
    39 
    39 
    40 /*****************************************************************************/
    40 /*****************************************************************************/
    41 
    41 
    42 /**
    42 /**
    43    Konstruktor einer EtherCAT-Domäne.
    43    Domain constructor.
    44 */
    44    \return 0 in case of success, else < 0
    45 
    45 */
    46 int ec_domain_init(ec_domain_t *domain, /**< Domäne */
    46 
    47                    ec_master_t *master, /**< Zugehöriger Master */
    47 int ec_domain_init(ec_domain_t *domain, /**< EtherCAT domain */
    48                    unsigned int index /**< Domänen-Index */
    48                    ec_master_t *master, /**< owning master */
       
    49                    unsigned int index /**< domain index */
    49                    )
    50                    )
    50 {
    51 {
    51     domain->master = master;
    52     domain->master = master;
    52     domain->index = index;
    53     domain->index = index;
    53     domain->data_size = 0;
    54     domain->data_size = 0;
    55     domain->response_count = 0xFFFFFFFF;
    56     domain->response_count = 0xFFFFFFFF;
    56 
    57 
    57     INIT_LIST_HEAD(&domain->field_regs);
    58     INIT_LIST_HEAD(&domain->field_regs);
    58     INIT_LIST_HEAD(&domain->commands);
    59     INIT_LIST_HEAD(&domain->commands);
    59 
    60 
    60     // Init kobject and add it to the hierarchy
    61     // init kobject and add it to the hierarchy
    61     memset(&domain->kobj, 0x00, sizeof(struct kobject));
    62     memset(&domain->kobj, 0x00, sizeof(struct kobject));
    62     kobject_init(&domain->kobj);
    63     kobject_init(&domain->kobj);
    63     domain->kobj.ktype = &ktype_ec_domain;
    64     domain->kobj.ktype = &ktype_ec_domain;
    64     domain->kobj.parent = &master->kobj;
    65     domain->kobj.parent = &master->kobj;
    65     if (kobject_set_name(&domain->kobj, "domain%i", index)) {
    66     if (kobject_set_name(&domain->kobj, "domain%i", index)) {
    71 }
    72 }
    72 
    73 
    73 /*****************************************************************************/
    74 /*****************************************************************************/
    74 
    75 
    75 /**
    76 /**
    76    Destruktor einer EtherCAT-Domäne.
    77    Domain destructor.
    77 */
    78 */
    78 
    79 
    79 void ec_domain_clear(struct kobject *kobj /**< Kobject der Domäne */)
    80 void ec_domain_clear(struct kobject *kobj /**< kobject of the domain */)
    80 {
    81 {
    81     ec_command_t *command, *next;
    82     ec_command_t *command, *next;
    82     ec_domain_t *domain;
    83     ec_domain_t *domain;
    83 
    84 
    84     domain = container_of(kobj, ec_domain_t, kobj);
    85     domain = container_of(kobj, ec_domain_t, kobj);
    96 }
    97 }
    97 
    98 
    98 /*****************************************************************************/
    99 /*****************************************************************************/
    99 
   100 
   100 /**
   101 /**
   101    Registriert ein Feld in einer Domäne.
   102    Registeres a data field in a domain.
   102 
   103    \return 0 in case of success, else < 0
   103    \return 0 bei Erfolg, < 0 bei Fehler
   104 */
   104 */
   105 
   105 
   106 int ec_domain_reg_field(ec_domain_t *domain, /**< EtherCAT domain */
   106 int ec_domain_reg_field(ec_domain_t *domain, /**< Domäne */
   107                         ec_slave_t *slave, /**< slave */
   107                         ec_slave_t *slave, /**< Slave */
   108                         const ec_sync_t *sync, /**< sync manager */
   108                         const ec_sync_t *sync, /**< Sync-Manager */
   109                         uint32_t field_offset, /**< data field offset */
   109                         uint32_t field_offset, /**< Datenfeld-Offset */
   110                         void **data_ptr /**< pointer to the process data
   110                         void **data_ptr /**< Adresse des Prozessdatenzeigers */
   111                                            pointer */
   111                         )
   112                         )
   112 {
   113 {
   113     ec_field_reg_t *field_reg;
   114     ec_field_reg_t *field_reg;
   114 
   115 
   115     if (!(field_reg =
   116     if (!(field_reg =
   134 }
   135 }
   135 
   136 
   136 /*****************************************************************************/
   137 /*****************************************************************************/
   137 
   138 
   138 /**
   139 /**
   139    Gibt die Liste der registrierten Datenfelder frei.
   140    Clears the list of the registered data fields.
   140 */
   141 */
   141 
   142 
   142 void ec_domain_clear_field_regs(ec_domain_t *domain)
   143 void ec_domain_clear_field_regs(ec_domain_t *domain /**< EtherCAT domain */)
   143 {
   144 {
   144     ec_field_reg_t *field_reg, *next;
   145     ec_field_reg_t *field_reg, *next;
   145 
   146 
   146     list_for_each_entry_safe(field_reg, next, &domain->field_regs, list) {
   147     list_for_each_entry_safe(field_reg, next, &domain->field_regs, list) {
   147         list_del(&field_reg->list);
   148         list_del(&field_reg->list);
   150 }
   151 }
   151 
   152 
   152 /*****************************************************************************/
   153 /*****************************************************************************/
   153 
   154 
   154 /**
   155 /**
   155    Alloziert ein Prozessdatenkommando und fügt es in die Liste ein.
   156    Allocates a process data command and appends it to the list.
   156 */
   157    \return 0 in case of success, else < 0
   157 
   158 */
   158 int ec_domain_add_command(ec_domain_t *domain, /**< Domäne */
   159 
   159                           uint32_t offset, /**< Logisches Offset */
   160 int ec_domain_add_command(ec_domain_t *domain, /**< EtherCAT domain */
   160                           size_t data_size /**< Größe der Kommando-Daten */
   161                           uint32_t offset, /**< logical offset */
       
   162                           size_t data_size /**< size of the command data */
   161                           )
   163                           )
   162 {
   164 {
   163     ec_command_t *command;
   165     ec_command_t *command;
   164 
   166 
   165     if (!(command = kmalloc(sizeof(ec_command_t), GFP_KERNEL))) {
   167     if (!(command = kmalloc(sizeof(ec_command_t), GFP_KERNEL))) {
   179 }
   181 }
   180 
   182 
   181 /*****************************************************************************/
   183 /*****************************************************************************/
   182 
   184 
   183 /**
   185 /**
   184    Erzeugt eine Domäne.
   186    Creates a domain.
   185 
   187    Reserves domain memory, calculates the logical addresses of the
   186    Reserviert den Speicher einer Domäne, berechnet die logischen Adressen der
   188    corresponding FMMUs and sets the process data pointer of the registered
   187    FMMUs und setzt die Prozessdatenzeiger der registrierten Felder.
   189    data fields.
   188 
   190    \return 0 in case of success, else < 0
   189    \return 0 bei Erfolg, < 0 bei Fehler
   191 */
   190 */
   192 
   191 
   193 int ec_domain_alloc(ec_domain_t *domain, /**< EtherCAT domain */
   192 int ec_domain_alloc(ec_domain_t *domain, /**< Domäne */
       
   193                     uint32_t base_address /**< Logische Basisadresse */
   194                     uint32_t base_address /**< Logische Basisadresse */
   194                     )
   195                     )
   195 {
   196 {
   196     ec_field_reg_t *field_reg;
   197     ec_field_reg_t *field_reg;
   197     ec_slave_t *slave;
   198     ec_slave_t *slave;
   274 }
   275 }
   275 
   276 
   276 /*****************************************************************************/
   277 /*****************************************************************************/
   277 
   278 
   278 /**
   279 /**
   279    Gibt die Anzahl der antwortenden Slaves aus.
   280    Sets the number of responding slaves and outputs it on demand.
   280 */
   281    This number isn't really the number of responding slaves, but the sum of
   281 
   282    the working counters of all domain commands. Some slaves increase the
   282 void ec_domain_response_count(ec_domain_t *domain, /**< Domäne */
   283    working counter by 2, some by 1.
   283                               unsigned int count /**< Neue Anzahl */
   284 */
       
   285 
       
   286 void ec_domain_response_count(ec_domain_t *domain, /**< EtherCAT domain */
       
   287                               unsigned int count /**< new WC sum */
   284                               )
   288                               )
   285 {
   289 {
   286     if (count != domain->response_count) {
   290     if (count != domain->response_count) {
   287         domain->response_count = count;
   291         domain->response_count = count;
   288         EC_INFO("Domain %i working counter change: %i\n", domain->index, count);
   292         EC_INFO("Domain %i working counter change: %i\n", domain->index,
   289     }
   293                 count);
   290 }
   294     }
   291 
   295 }
   292 /*****************************************************************************/
   296 
   293 
   297 /*****************************************************************************/
   294 /**
   298 
   295    Formatiert Attribut-Daten für lesenden Zugriff im SysFS
   299 /**
   296 
   300    Formats attribute data for SysFS reading.
   297    \return Anzahl Bytes im Speicher
   301    \return number of bytes to read
   298 */
   302 */
   299 
   303 
   300 ssize_t ec_show_domain_attribute(struct kobject *kobj, /**< KObject */
   304 ssize_t ec_show_domain_attribute(struct kobject *kobj, /**< kobject */
   301                                  struct attribute *attr, /**< Attribut */
   305                                  struct attribute *attr, /**< attribute */
   302                                  char *buffer /**< Speicher für die Daten */
   306                                  char *buffer /**< memory to store data in */
   303                                  )
   307                                  )
   304 {
   308 {
   305     ec_domain_t *domain = container_of(kobj, ec_domain_t, kobj);
   309     ec_domain_t *domain = container_of(kobj, ec_domain_t, kobj);
   306 
   310 
   307     if (attr == &attr_data_size) {
   311     if (attr == &attr_data_size) {
   310 
   314 
   311     return 0;
   315     return 0;
   312 }
   316 }
   313 
   317 
   314 /******************************************************************************
   318 /******************************************************************************
   315  *
   319  *  Realtime interface
   316  * Echtzeitschnittstelle
       
   317  *
       
   318  *****************************************************************************/
   320  *****************************************************************************/
   319 
   321 
   320 /**
   322 /**
   321    Registriert ein Datenfeld innerhalb einer Domäne.
   323    Registers a data field in a domain.
   322 
   324    - If \a data_ptr is NULL, the slave is only checked against its type.
   323    - Ist \a data_ptr NULL, so wird der Slave nur auf den Typ überprüft.
   325    - If \a field_count is 0, it is assumed that one data field is to be
   324    - Wenn \a field_count 0 ist, wird angenommen, dass 1 Feld registriert werden
   326    registered.
   325      soll.
   327    - If \a field_count is greater then 1, it is assumed that \a data_ptr
   326    - Wenn \a field_count größer als 1 ist, wird angenommen, dass \a data_ptr
   328    is an array of the respective size.
   327      auf ein entsprechend großes Array zeigt.
   329    \return pointer to the slave on success, else NULL
   328 
       
   329    \return Zeiger auf den Slave bei Erfolg, sonst NULL
       
   330 */
   330 */
   331 
   331 
   332 ec_slave_t *ecrt_domain_register_field(ec_domain_t *domain,
   332 ec_slave_t *ecrt_domain_register_field(ec_domain_t *domain,
   333                                        /**< Domäne */
   333                                        /**< EtherCAT domain */
   334                                        const char *address,
   334                                        const char *address,
   335                                        /**< ASCII-Addresse des Slaves,
   335                                        /**< ASCII address of the slave,
   336                                           siehe ecrt_master_get_slave() */
   336                                           see ecrt_master_get_slave() */
   337                                        const char *vendor_name,
   337                                        const char *vendor_name,
   338                                        /**< Herstellername */
   338                                        /**< vendor name */
   339                                        const char *product_name,
   339                                        const char *product_name,
   340                                        /**< Produktname */
   340                                        /**< product name */
   341                                        void **data_ptr,
   341                                        void **data_ptr,
   342                                        /**< Adresse des Zeigers auf die
   342                                        /**< address of the process data
   343                                           Prozessdaten */
   343                                           pointer */
   344                                        const char *field_name,
   344                                        const char *field_name,
   345                                        /**< Name des Datenfeldes */
   345                                        /**< data field name */
   346                                        unsigned int field_index,
   346                                        unsigned int field_index,
   347                                        /**< Gibt an, ab welchem Feld mit
   347                                        /**< offset of data fields with
   348                                           Typ \a field_type gezählt
   348                                           \a field_type  */
   349                                           werden soll. */
       
   350                                        unsigned int field_count
   349                                        unsigned int field_count
   351                                        /**< Anzahl Felder selben Typs */
   350                                        /**< number of data fields (with
       
   351                                           the same type) to register */
   352                                        )
   352                                        )
   353 {
   353 {
   354     ec_slave_t *slave;
   354     ec_slave_t *slave;
   355     const ec_slave_type_t *type;
   355     const ec_slave_type_t *type;
   356     ec_master_t *master;
   356     ec_master_t *master;
   359     unsigned int field_counter, i, j, orig_field_index, orig_field_count;
   359     unsigned int field_counter, i, j, orig_field_index, orig_field_count;
   360     uint32_t field_offset;
   360     uint32_t field_offset;
   361 
   361 
   362     master = domain->master;
   362     master = domain->master;
   363 
   363 
   364     // Adresse übersetzen
   364     // translate address
   365     if (!(slave = ecrt_master_get_slave(master, address))) return NULL;
   365     if (!(slave = ecrt_master_get_slave(master, address))) return NULL;
   366 
   366 
   367     if (!(type = slave->type)) {
   367     if (!(type = slave->type)) {
   368         EC_ERR("Slave \"%s\" (position %i) has unknown type!\n", address,
   368         EC_ERR("Slave \"%s\" (position %i) has unknown type!\n", address,
   369                slave->ring_position);
   369                slave->ring_position);
   377                product_name, type->vendor_name, type->product_name);
   377                product_name, type->vendor_name, type->product_name);
   378         return NULL;
   378         return NULL;
   379     }
   379     }
   380 
   380 
   381     if (!data_ptr) {
   381     if (!data_ptr) {
   382         // Wenn data_ptr NULL, Slave als registriert ansehen (nicht warnen).
   382         // data_ptr is NULL => mark slave as "registered" (do not warn)
   383         slave->registered = 1;
   383         slave->registered = 1;
   384     }
   384     }
   385 
   385 
   386     if (!field_count) field_count = 1;
   386     if (!field_count) field_count = 1;
   387     orig_field_index = field_index;
   387     orig_field_index = field_index;
   413 }
   413 }
   414 
   414 
   415 /*****************************************************************************/
   415 /*****************************************************************************/
   416 
   416 
   417 /**
   417 /**
   418    Registriert eine ganze Liste von Datenfeldern innerhalb einer Domäne.
   418    Registeres a bunch of data fields.
   419 
   419    Caution! The list has to be terminated with a NULL structure ({})!
   420    Achtung: Die Liste muss mit einer NULL-Struktur ({}) abgeschlossen sein!
   420    \return 0 in case of success, else < 0
   421 
       
   422    \return 0 bei Erfolg, sonst < 0
       
   423 */
   421 */
   424 
   422 
   425 int ecrt_domain_register_field_list(ec_domain_t *domain,
   423 int ecrt_domain_register_field_list(ec_domain_t *domain,
   426                                     /**< Domäne */
   424                                     /**< EtherCAT domain */
   427                                     const ec_field_init_t *fields
   425                                     const ec_field_init_t *fields
   428                                     /**< Array mit Datenfeldern */
   426                                     /**< array of data field registrations */
   429                                     )
   427                                     )
   430 {
   428 {
   431     const ec_field_init_t *field;
   429     const ec_field_init_t *field;
   432 
   430 
   433     for (field = fields; field->slave_address; field++)
   431     for (field = fields; field->slave_address; field++)
   442 }
   440 }
   443 
   441 
   444 /*****************************************************************************/
   442 /*****************************************************************************/
   445 
   443 
   446 /**
   444 /**
   447    Setzt Prozessdaten-Kommandos in die Warteschlange des Masters.
   445    Places all process data commands in the masters command queue.
   448 */
   446 */
   449 
   447 
   450 void ecrt_domain_queue(ec_domain_t *domain /**< Domäne */)
   448 void ecrt_domain_queue(ec_domain_t *domain /**< EtherCAT domain */)
   451 {
   449 {
   452     ec_command_t *command;
   450     ec_command_t *command;
   453 
   451 
   454     list_for_each_entry(command, &domain->commands, list) {
   452     list_for_each_entry(command, &domain->commands, list) {
   455         ec_master_queue_command(domain->master, command);
   453         ec_master_queue_command(domain->master, command);
   457 }
   455 }
   458 
   456 
   459 /*****************************************************************************/
   457 /*****************************************************************************/
   460 
   458 
   461 /**
   459 /**
   462    Verarbeitet empfangene Prozessdaten.
   460    Processes received process data.
   463 */
   461 */
   464 
   462 
   465 void ecrt_domain_process(ec_domain_t *domain /**< Domäne */)
   463 void ecrt_domain_process(ec_domain_t *domain /**< EtherCAT domain */)
   466 {
   464 {
   467     unsigned int working_counter_sum;
   465     unsigned int working_counter_sum;
   468     ec_command_t *command;
   466     ec_command_t *command;
   469 
   467 
   470     working_counter_sum = 0;
   468     working_counter_sum = 0;
   479 }
   477 }
   480 
   478 
   481 /*****************************************************************************/
   479 /*****************************************************************************/
   482 
   480 
   483 /**
   481 /**
   484    Gibt den Status einer Domäne zurück.
   482    Returns the state of a domain.
   485 
   483    \return 0 if all commands were received, else -1.
   486    \return 0 wenn alle Kommandos empfangen wurden, sonst -1.
   484 */
   487 */
   485 
   488 
   486 int ecrt_domain_state(ec_domain_t *domain /**< EtherCAT domain */)
   489 int ecrt_domain_state(ec_domain_t *domain /**< Domäne */)
       
   490 {
   487 {
   491     ec_command_t *command;
   488     ec_command_t *command;
   492 
   489 
   493     list_for_each_entry(command, &domain->commands, list) {
   490     list_for_each_entry(command, &domain->commands, list) {
   494         if (command->state != EC_CMD_RECEIVED) return -1;
   491         if (command->state != EC_CMD_RECEIVED) return -1;
   504 EXPORT_SYMBOL(ecrt_domain_queue);
   501 EXPORT_SYMBOL(ecrt_domain_queue);
   505 EXPORT_SYMBOL(ecrt_domain_process);
   502 EXPORT_SYMBOL(ecrt_domain_process);
   506 EXPORT_SYMBOL(ecrt_domain_state);
   503 EXPORT_SYMBOL(ecrt_domain_state);
   507 
   504 
   508 /*****************************************************************************/
   505 /*****************************************************************************/
   509 
       
   510 /* Emacs-Konfiguration
       
   511 ;;; Local Variables: ***
       
   512 ;;; c-basic-offset:4 ***
       
   513 ;;; End: ***
       
   514 */