master/master.c
changeset 182 8c0bc99229a9
parent 179 fb4c9dd11ca0
child 184 2fc86cec12df
equal deleted inserted replaced
181:3e9155836bc7 182:8c0bc99229a9
    62                    )
    62                    )
    63 {
    63 {
    64     EC_INFO("Initializing master %i.\n", index);
    64     EC_INFO("Initializing master %i.\n", index);
    65 
    65 
    66     master->index = index;
    66     master->index = index;
    67     master->slaves = NULL;
       
    68     master->device = NULL;
    67     master->device = NULL;
    69     master->reserved = 0;
    68     master->reserved = 0;
    70 
    69 
       
    70     INIT_LIST_HEAD(&master->slaves);
    71     INIT_LIST_HEAD(&master->command_queue);
    71     INIT_LIST_HEAD(&master->command_queue);
    72     INIT_LIST_HEAD(&master->domains);
    72     INIT_LIST_HEAD(&master->domains);
    73     INIT_LIST_HEAD(&master->eoe_slaves);
    73     INIT_LIST_HEAD(&master->eoe_slaves);
    74 
    74 
    75     // Init kobject and add it to the hierarchy
    75     // Init kobject and add it to the hierarchy
   128 
   128 
   129 void ec_master_reset(ec_master_t *master
   129 void ec_master_reset(ec_master_t *master
   130                      /**< Zeiger auf den zurückzusetzenden Master */
   130                      /**< Zeiger auf den zurückzusetzenden Master */
   131                      )
   131                      )
   132 {
   132 {
   133     unsigned int i;
   133     ec_slave_t *slave, *next_s;
   134     ec_command_t *command, *next_c;
   134     ec_command_t *command, *next_c;
   135     ec_domain_t *domain, *next_d;
   135     ec_domain_t *domain, *next_d;
   136     ec_eoe_t *eoe, *next_eoe;
   136     ec_eoe_t *eoe, *next_eoe;
   137 
   137 
   138     // Alle Slaves entfernen
   138     // Alle Slaves entfernen
   139     if (master->slaves) {
   139     list_for_each_entry_safe(slave, next_s, &master->slaves, list) {
   140         for (i = 0; i < master->slave_count; i++)
   140         list_del(&slave->list);
   141             ec_slave_clear(master->slaves + i);
   141         kobject_del(&slave->kobj);
   142         kfree(master->slaves);
   142         kobject_put(&slave->kobj);
   143         master->slaves = NULL;
       
   144     }
   143     }
   145     master->slave_count = 0;
   144     master->slave_count = 0;
   146 
   145 
   147     // Kommando-Warteschlange leeren
   146     // Kommando-Warteschlange leeren
   148     list_for_each_entry_safe(command, next_c, &master->command_queue, queue) {
   147     list_for_each_entry_safe(command, next_c, &master->command_queue, queue) {
       
   148         list_del_init(&command->queue);
   149         command->state = EC_CMD_ERROR;
   149         command->state = EC_CMD_ERROR;
   150         list_del_init(&command->queue);
       
   151     }
   150     }
   152 
   151 
   153     // Domain-Liste leeren
   152     // Domain-Liste leeren
   154     list_for_each_entry_safe(domain, next_d, &master->domains, list) {
   153     list_for_each_entry_safe(domain, next_d, &master->domains, list) {
   155         list_del(&domain->list);
   154         list_del(&domain->list);
   453    \return 0 bei Erfolg, sonst < 0
   452    \return 0 bei Erfolg, sonst < 0
   454 */
   453 */
   455 
   454 
   456 int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
   455 int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
   457 {
   456 {
   458     ec_slave_t *slave;
   457     ec_slave_t *slave, *next;
   459     ec_slave_ident_t *ident;
   458     ec_slave_ident_t *ident;
   460     unsigned int i;
   459     unsigned int i;
   461     ec_command_t *command;
   460     ec_command_t *command;
   462     ec_eoe_t *eoe;
   461     ec_eoe_t *eoe;
   463 
   462     uint16_t buscoupler_index, index_after_buscoupler;
   464     if (master->slaves || master->slave_count) {
   463 
       
   464     if (!list_empty(&master->slaves)) {
   465         EC_ERR("Slave scan already done!\n");
   465         EC_ERR("Slave scan already done!\n");
   466         return -1;
   466         return -1;
   467     }
   467     }
   468 
   468 
   469     command = &master->simple_command;
   469     command = &master->simple_command;
   474     master->slave_count = command->working_counter;
   474     master->slave_count = command->working_counter;
   475     EC_INFO("Found %i slaves on bus.\n", master->slave_count);
   475     EC_INFO("Found %i slaves on bus.\n", master->slave_count);
   476 
   476 
   477     if (!master->slave_count) return 0;
   477     if (!master->slave_count) return 0;
   478 
   478 
   479     if (!(master->slaves = (ec_slave_t *)
       
   480           kmalloc(master->slave_count * sizeof(ec_slave_t), GFP_KERNEL))) {
       
   481         EC_ERR("Failed to allocate slaves!\n");
       
   482         return -1;
       
   483     }
       
   484 
       
   485     // Init slaves
   479     // Init slaves
   486     for (i = 0; i < master->slave_count; i++) {
   480     for (i = 0; i < master->slave_count; i++) {
   487         slave = master->slaves + i;
   481         if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_KERNEL))) {
   488         ec_slave_init(slave, master);
   482             EC_ERR("Failed to allocate slave %i!\n", i);
   489         slave->ring_position = i;
   483             goto out_free;
   490         slave->station_address = i + 1;
   484         }
   491     }
   485 
       
   486         if (ec_slave_init(slave, master, i, i + 1)) goto out_free;
       
   487 
       
   488         if (kobject_add(&slave->kobj)) {
       
   489             EC_ERR("Failed to add kobject.\n");
       
   490             kobject_put(&slave->kobj); // free
       
   491             goto out_free;
       
   492         }
       
   493 
       
   494         list_add_tail(&slave->list, &master->slaves);
       
   495     }
       
   496 
       
   497     buscoupler_index = 0xFFFF;
       
   498     index_after_buscoupler = 0;
   492 
   499 
   493     // For every slave on the bus
   500     // For every slave on the bus
   494     for (i = 0; i < master->slave_count; i++) {
   501     list_for_each_entry(slave, &master->slaves, list) {
   495         slave = master->slaves + i;
       
   496 
   502 
   497         // Write station address
   503         // Write station address
   498         if (ec_command_apwr(command, slave->ring_position,
   504         if (ec_command_apwr(command, slave->ring_position, 0x0010,
   499                             0x0010, sizeof(uint16_t))) return -1;
   505                             sizeof(uint16_t))) goto out_free;
   500         EC_WRITE_U16(command->data, slave->station_address);
   506         EC_WRITE_U16(command->data, slave->station_address);
   501         if (unlikely(ec_master_simple_io(master, command))) {
   507         if (unlikely(ec_master_simple_io(master, command))) {
   502             EC_ERR("Writing station address failed on slave %i!\n", i);
   508             EC_ERR("Writing station address failed on slave %i!\n",
   503             return -1;
   509                    slave->ring_position);
       
   510             goto out_free;
   504         }
   511         }
   505 
   512 
   506         // Fetch all slave information
   513         // Fetch all slave information
   507         if (ec_slave_fetch(slave)) return -1;
   514         if (ec_slave_fetch(slave)) goto out_free;
   508 
   515 
   509         // Search for identification in "database"
   516         // Search for identification in "database"
   510         ident = slave_idents;
   517         ident = slave_idents;
   511         while (ident->type) {
   518         while (ident->type) {
   512             if (unlikely(ident->vendor_id == slave->sii_vendor_id
   519             if (unlikely(ident->vendor_id == slave->sii_vendor_id
   519 
   526 
   520         if (!slave->type)
   527         if (!slave->type)
   521             EC_WARN("Unknown slave device (vendor 0x%08X, code 0x%08X) at"
   528             EC_WARN("Unknown slave device (vendor 0x%08X, code 0x%08X) at"
   522                     " position %i.\n", slave->sii_vendor_id,
   529                     " position %i.\n", slave->sii_vendor_id,
   523                     slave->sii_product_code, i);
   530                     slave->sii_product_code, i);
       
   531         else {
       
   532             if (slave->type->special == EC_TYPE_BUS_COUPLER) {
       
   533                 buscoupler_index++;
       
   534                 index_after_buscoupler = 0;
       
   535             }
       
   536         }
       
   537 
       
   538         slave->buscoupler_index = buscoupler_index;
       
   539         slave->index_after_buscoupler = index_after_buscoupler;
       
   540         index_after_buscoupler++;
   524 
   541 
   525         // Does the slave support EoE?
   542         // Does the slave support EoE?
   526         if (slave->sii_mailbox_protocols & EC_MBOX_EOE) {
   543         if (slave->sii_mailbox_protocols & EC_MBOX_EOE) {
   527             if (!(eoe = (ec_eoe_t *) kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
   544             if (!(eoe = (ec_eoe_t *) kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
   528                 EC_ERR("Failed to allocate EoE-Object.\n");
   545                 EC_ERR("Failed to allocate EoE-Object.\n");
   529                 return -1;
   546                 goto out_free;
   530             }
   547             }
   531 
   548 
   532             ec_eoe_init(eoe, slave);
   549             ec_eoe_init(eoe, slave);
   533             list_add_tail(&eoe->list, &master->eoe_slaves);
   550             list_add_tail(&eoe->list, &master->eoe_slaves);
   534         }
   551         }
   535     }
   552     }
   536 
   553 
   537     return 0;
   554     return 0;
       
   555 
       
   556  out_free:
       
   557     list_for_each_entry_safe(slave, next, &master->slaves, list) {
       
   558         list_del(&slave->list);
       
   559         kobject_del(&slave->kobj);
       
   560         kobject_put(&slave->kobj);
       
   561     }
       
   562     return -1;
   538 }
   563 }
   539 
   564 
   540 /*****************************************************************************/
   565 /*****************************************************************************/
   541 
   566 
   542 /**
   567 /**
   598                                   const char *address /**< Address-String */
   623                                   const char *address /**< Address-String */
   599                                   )
   624                                   )
   600 {
   625 {
   601     unsigned long first, second;
   626     unsigned long first, second;
   602     char *remainder, *remainder2;
   627     char *remainder, *remainder2;
   603     unsigned int i, alias_requested, alias_slave_index, alias_found;
   628     unsigned int alias_requested, alias_found;
   604     int coupler_idx, slave_idx;
   629     ec_slave_t *alias_slave = NULL, *slave;
   605     ec_slave_t *slave;
       
   606 
   630 
   607     if (!address || address[0] == 0) return NULL;
   631     if (!address || address[0] == 0) return NULL;
   608 
   632 
   609     alias_requested = 0;
   633     alias_requested = 0;
   610     alias_slave_index = 0;
       
   611     if (address[0] == '#') {
   634     if (address[0] == '#') {
   612         alias_requested = 1;
   635         alias_requested = 1;
   613         address++;
   636         address++;
   614     }
   637     }
   615 
   638 
   619         return NULL;
   642         return NULL;
   620     }
   643     }
   621 
   644 
   622     if (alias_requested) {
   645     if (alias_requested) {
   623         alias_found = 0;
   646         alias_found = 0;
   624         for (i = 0; i < master->slave_count; i++) {
   647         list_for_each_entry(alias_slave, &master->slaves, list) {
   625             if (master->slaves[i].sii_alias == first) {
   648             if (alias_slave->sii_alias == first) {
   626                 alias_slave_index = i;
       
   627                 alias_found = 1;
   649                 alias_found = 1;
   628                 break;
   650                 break;
   629             }
   651             }
   630         }
   652         }
   631         if (!alias_found) {
   653         if (!alias_found) {
   634         }
   656         }
   635     }
   657     }
   636 
   658 
   637     if (!remainder[0]) { // absolute position
   659     if (!remainder[0]) { // absolute position
   638         if (alias_requested) {
   660         if (alias_requested) {
   639             return master->slaves + alias_slave_index;
   661             return alias_slave;
   640         }
   662         }
   641         else {
   663         else {
   642             if (first < master->slave_count) {
   664             list_for_each_entry(slave, &master->slaves, list) {
   643                 return master->slaves + first;
   665                 if (slave->ring_position == first) return slave;
   644             }
   666             }
   645             EC_ERR("Slave address \"%s\" - Absolute position invalid!\n",
   667             EC_ERR("Slave address \"%s\" - Absolute position invalid!\n",
   646                    address);
   668                    address);
   647         }
   669         }
   648     }
   670     }
   659             EC_ERR("Slave address \"%s\" - Invalid trailer!\n", address);
   681             EC_ERR("Slave address \"%s\" - Invalid trailer!\n", address);
   660             return NULL;
   682             return NULL;
   661         }
   683         }
   662 
   684 
   663         if (alias_requested) {
   685         if (alias_requested) {
   664             for (i = alias_slave_index + 1; i < master->slave_count; i++) {
   686             list_for_each_entry(slave, &master->slaves, list) {
   665                 slave = master->slaves + i;
   687                 if (slave->buscoupler_index == alias_slave->buscoupler_index
   666                 if (!slave->type ||
   688                     && alias_slave->index_after_buscoupler == 0
   667                     slave->type->special == EC_TYPE_BUS_COUPLER) break;
   689                     && slave->index_after_buscoupler == second)
   668                 if (i - alias_slave_index == second) return slave;
   690                     return slave;
   669             }
   691             }
   670             EC_ERR("Slave address \"%s\" - Bus coupler %i has no %lu. slave"
   692             EC_ERR("Slave address \"%s\" - Bus coupler %i has no %lu. slave"
   671                    " following!\n", address,
   693                    " following!\n", address, alias_slave->ring_position,
   672                    (master->slaves + alias_slave_index)->ring_position,
       
   673                    second);
   694                    second);
   674             return NULL;
   695             return NULL;
   675         }
   696         }
   676         else {
   697         else {
   677             coupler_idx = -1;
   698             list_for_each_entry(slave, &master->slaves, list) {
   678             slave_idx = 0;
   699                 if (slave->buscoupler_index == first
   679             for (i = 0; i < master->slave_count; i++, slave_idx++) {
   700                     && slave->index_after_buscoupler == second) return slave;
   680                 slave = master->slaves + i;
       
   681                 if (!slave->type) continue;
       
   682                 if (slave->type->special == EC_TYPE_BUS_COUPLER) {
       
   683                     coupler_idx++;
       
   684                     slave_idx = 0;
       
   685                 }
       
   686                 if (coupler_idx == first && slave_idx == second) return slave;
       
   687             }
   701             }
   688         }
   702         }
   689     }
   703     }
   690     else
   704     else
   691         EC_ERR("Slave address \"%s\" - Invalid format!\n", address);
   705         EC_ERR("Slave address \"%s\" - Invalid format!\n", address);
   885    \return 0 bei Erfolg, sonst < 0
   899    \return 0 bei Erfolg, sonst < 0
   886 */
   900 */
   887 
   901 
   888 int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
   902 int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
   889 {
   903 {
   890     unsigned int i, j;
   904     unsigned int j;
   891     ec_slave_t *slave;
   905     ec_slave_t *slave;
   892     ec_command_t *command;
   906     ec_command_t *command;
   893     const ec_sync_t *sync;
   907     const ec_sync_t *sync;
   894     const ec_slave_type_t *type;
   908     const ec_slave_type_t *type;
   895     const ec_fmmu_t *fmmu;
   909     const ec_fmmu_t *fmmu;
   913         }
   927         }
   914         domain_offset += domain->data_size;
   928         domain_offset += domain->data_size;
   915     }
   929     }
   916 
   930 
   917     // Slaves aktivieren
   931     // Slaves aktivieren
   918     for (i = 0; i < master->slave_count; i++) {
   932     list_for_each_entry(slave, &master->slaves, list) {
   919         slave = master->slaves + i;
       
   920 
   933 
   921         // Change state to INIT
   934         // Change state to INIT
   922         if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_INIT)))
   935         if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_INIT)))
   923             return -1;
   936             return -1;
   924 
   937 
   925         // Check if slave was registered...
   938         // Check if slave was registered...
   926         type = slave->type;
   939         type = slave->type;
   927         if (!type) EC_WARN("Slave %i has unknown type!\n", i);
   940         if (!type)
       
   941             EC_WARN("Slave %i has unknown type!\n", slave->ring_position);
   928 
   942 
   929         // Check and reset CRC fault counters
   943         // Check and reset CRC fault counters
   930         ec_slave_check_crc(slave);
   944         ec_slave_check_crc(slave);
   931 
   945 
   932         // Resetting FMMUs
   946         // Resetting FMMUs
  1077 */
  1091 */
  1078 
  1092 
  1079 void ecrt_master_deactivate(ec_master_t *master /**< EtherCAT-Master */)
  1093 void ecrt_master_deactivate(ec_master_t *master /**< EtherCAT-Master */)
  1080 {
  1094 {
  1081     ec_slave_t *slave;
  1095     ec_slave_t *slave;
  1082     unsigned int i;
  1096 
  1083 
  1097     list_for_each_entry(slave, &master->slaves, list) {
  1084     for (i = 0; i < master->slave_count; i++)
       
  1085     {
       
  1086         slave = master->slaves + i;
       
  1087         ec_slave_check_crc(slave);
  1098         ec_slave_check_crc(slave);
  1088         ec_slave_state_change(slave, EC_SLAVE_STATE_INIT);
  1099         ec_slave_state_change(slave, EC_SLAVE_STATE_INIT);
  1089     }
  1100     }
  1090 }
  1101 }
  1091 
  1102 
  1101 */
  1112 */
  1102 
  1113 
  1103 int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT-Master */)
  1114 int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT-Master */)
  1104 {
  1115 {
  1105     ec_slave_t *slave;
  1116     ec_slave_t *slave;
  1106     unsigned int i;
  1117 
  1107 
  1118     list_for_each_entry(slave, &master->slaves, list) {
  1108     for (i = 0; i < master->slave_count; i++) {
       
  1109         slave = master->slaves + i;
       
  1110         if (slave->sii_mailbox_protocols & EC_MBOX_COE) {
  1119         if (slave->sii_mailbox_protocols & EC_MBOX_COE) {
  1111             if (unlikely(ec_slave_fetch_sdo_list(slave))) {
  1120             if (unlikely(ec_slave_fetch_sdo_list(slave))) {
  1112                 EC_ERR("Failed to fetch SDO list on slave %i!\n",
  1121                 EC_ERR("Failed to fetch SDO list on slave %i!\n",
  1113                        slave->ring_position);
  1122                        slave->ring_position);
  1114                 return -1;
  1123                 return -1;
  1317 
  1326 
  1318 void ecrt_master_print(const ec_master_t *master, /**< EtherCAT-Master */
  1327 void ecrt_master_print(const ec_master_t *master, /**< EtherCAT-Master */
  1319                        unsigned int verbosity /**< Geschwätzigkeit */
  1328                        unsigned int verbosity /**< Geschwätzigkeit */
  1320                        )
  1329                        )
  1321 {
  1330 {
  1322     unsigned int i;
  1331     ec_slave_t *slave;
  1323     ec_eoe_t *eoe;
  1332     ec_eoe_t *eoe;
  1324 
  1333 
  1325     EC_INFO("*** Begin master information ***\n");
  1334     EC_INFO("*** Begin master information ***\n");
  1326     if (master->slave_count) {
  1335     if (master->slave_count) {
  1327         EC_INFO("Slave list:\n");
  1336         EC_INFO("Slave list:\n");
  1328         for (i = 0; i < master->slave_count; i++)
  1337         list_for_each_entry(slave, &master->slaves, list)
  1329             ec_slave_print(&master->slaves[i], verbosity);
  1338             ec_slave_print(slave, verbosity);
  1330     }
  1339     }
  1331     if (!list_empty(&master->eoe_slaves)) {
  1340     if (!list_empty(&master->eoe_slaves)) {
  1332         EC_INFO("Ethernet-over-EtherCAT (EoE) objects:\n");
  1341         EC_INFO("Ethernet-over-EtherCAT (EoE) objects:\n");
  1333         list_for_each_entry(eoe, &master->eoe_slaves, list) {
  1342         list_for_each_entry(eoe, &master->eoe_slaves, list) {
  1334             ec_eoe_print(eoe);
  1343             ec_eoe_print(eoe);