152 INIT_LIST_HEAD(&slave->sii_pdos); |
152 INIT_LIST_HEAD(&slave->sii_pdos); |
153 INIT_LIST_HEAD(&slave->sdo_dictionary); |
153 INIT_LIST_HEAD(&slave->sdo_dictionary); |
154 INIT_LIST_HEAD(&slave->sdo_confs); |
154 INIT_LIST_HEAD(&slave->sdo_confs); |
155 |
155 |
156 slave->sdo_dictionary_fetched = 0; |
156 slave->sdo_dictionary_fetched = 0; |
|
157 slave->pdo_mapping_fetched = 0; |
157 slave->jiffies_preop = 0; |
158 slave->jiffies_preop = 0; |
158 |
159 |
159 for (i = 0; i < 4; i++) { |
160 for (i = 0; i < 4; i++) { |
160 slave->dl_link[i] = 0; |
161 slave->dl_link[i] = 0; |
161 slave->dl_loop[i] = 0; |
162 slave->dl_loop[i] = 0; |
385 |
388 |
386 /*****************************************************************************/ |
389 /*****************************************************************************/ |
387 |
390 |
388 /** |
391 /** |
389 Fetches data from a STRING category. |
392 Fetches data from a STRING category. |
|
393 \todo range checking |
390 \return 0 in case of success, else < 0 |
394 \return 0 in case of success, else < 0 |
391 */ |
395 */ |
392 |
396 |
393 int ec_slave_fetch_sii_strings( |
397 int ec_slave_fetch_sii_strings( |
394 ec_slave_t *slave, /**< EtherCAT slave */ |
398 ec_slave_t *slave, /**< EtherCAT slave */ |
395 const uint8_t *data /**< category data */ |
399 const uint8_t *data, /**< category data */ |
|
400 size_t data_size /**< number of bytes */ |
396 ) |
401 ) |
397 { |
402 { |
398 int i; |
403 int i; |
399 size_t size; |
404 size_t size; |
400 off_t offset; |
405 off_t offset; |
441 /** |
446 /** |
442 Fetches data from a GENERAL category. |
447 Fetches data from a GENERAL category. |
443 \return 0 in case of success, else < 0 |
448 \return 0 in case of success, else < 0 |
444 */ |
449 */ |
445 |
450 |
446 void ec_slave_fetch_sii_general( |
451 int ec_slave_fetch_sii_general( |
447 ec_slave_t *slave, /**< EtherCAT slave */ |
452 ec_slave_t *slave, /**< EtherCAT slave */ |
448 const uint8_t *data /**< category data */ |
453 const uint8_t *data, /**< category data */ |
|
454 size_t data_size /**< size in bytes */ |
449 ) |
455 ) |
450 { |
456 { |
451 unsigned int i; |
457 unsigned int i; |
|
458 |
|
459 if (data_size != 32) { |
|
460 EC_ERR("Wrong size of general category (%u/32) in slave %u.\n", |
|
461 data_size, slave->ring_position); |
|
462 return -1; |
|
463 } |
452 |
464 |
453 slave->sii_group = ec_slave_sii_string(slave, data[0]); |
465 slave->sii_group = ec_slave_sii_string(slave, data[0]); |
454 slave->sii_image = ec_slave_sii_string(slave, data[1]); |
466 slave->sii_image = ec_slave_sii_string(slave, data[1]); |
455 slave->sii_order = ec_slave_sii_string(slave, data[2]); |
467 slave->sii_order = ec_slave_sii_string(slave, data[2]); |
456 slave->sii_name = ec_slave_sii_string(slave, data[3]); |
468 slave->sii_name = ec_slave_sii_string(slave, data[3]); |
458 for (i = 0; i < 4; i++) |
470 for (i = 0; i < 4; i++) |
459 slave->sii_physical_layer[i] = |
471 slave->sii_physical_layer[i] = |
460 (data[4] & (0x03 << (i * 2))) >> (i * 2); |
472 (data[4] & (0x03 << (i * 2))) >> (i * 2); |
461 |
473 |
462 slave->sii_current_on_ebus = EC_READ_S16(data + 0x0C); |
474 slave->sii_current_on_ebus = EC_READ_S16(data + 0x0C); |
|
475 |
|
476 return 0; |
463 } |
477 } |
464 |
478 |
465 /*****************************************************************************/ |
479 /*****************************************************************************/ |
466 |
480 |
467 /** |
481 /** |
470 */ |
484 */ |
471 |
485 |
472 int ec_slave_fetch_sii_syncs( |
486 int ec_slave_fetch_sii_syncs( |
473 ec_slave_t *slave, /**< EtherCAT slave */ |
487 ec_slave_t *slave, /**< EtherCAT slave */ |
474 const uint8_t *data, /**< category data */ |
488 const uint8_t *data, /**< category data */ |
475 size_t word_count /**< number of words */ |
489 size_t data_size /**< number of bytes */ |
476 ) |
490 ) |
477 { |
491 { |
478 unsigned int i; |
492 unsigned int i; |
479 ec_sync_t *sync; |
493 ec_sync_t *sync; |
480 |
494 size_t memsize; |
481 // sync manager struct is 4 words long |
495 |
482 slave->sii_sync_count = word_count / 4; |
496 // one sync manager struct is 4 words long |
483 |
497 if (data_size % 8) { |
484 if (!(slave->sii_syncs = |
498 EC_ERR("Invalid SII sync manager size %u in slave %u.\n", |
485 kmalloc(sizeof(ec_sync_t) * slave->sii_sync_count, |
499 data_size, slave->ring_position); |
486 GFP_KERNEL))) { |
500 return -1; |
487 EC_ERR("Failed to allocate memory for sync managers.\n"); |
501 } |
|
502 |
|
503 slave->sii_sync_count = data_size / 8; |
|
504 |
|
505 memsize = sizeof(ec_sync_t) * slave->sii_sync_count; |
|
506 if (!(slave->sii_syncs = kmalloc(memsize, GFP_KERNEL))) { |
|
507 EC_ERR("Failed to allocate %u bytes for sync managers.\n", |
|
508 memsize); |
488 slave->sii_sync_count = 0; |
509 slave->sii_sync_count = 0; |
489 return -1; |
510 return -1; |
490 } |
511 } |
491 |
512 |
492 for (i = 0; i < slave->sii_sync_count; i++, data += 8) { |
513 for (i = 0; i < slave->sii_sync_count; i++, data += 8) { |
510 */ |
531 */ |
511 |
532 |
512 int ec_slave_fetch_sii_pdos( |
533 int ec_slave_fetch_sii_pdos( |
513 ec_slave_t *slave, /**< EtherCAT slave */ |
534 ec_slave_t *slave, /**< EtherCAT slave */ |
514 const uint8_t *data, /**< category data */ |
535 const uint8_t *data, /**< category data */ |
515 size_t word_count, /**< number of words */ |
536 size_t data_size, /**< number of bytes */ |
516 ec_pdo_type_t pdo_type /**< PDO type */ |
537 ec_pdo_type_t pdo_type /**< PDO type */ |
517 ) |
538 ) |
518 { |
539 { |
519 ec_pdo_t *pdo; |
540 ec_pdo_t *pdo; |
520 ec_pdo_entry_t *entry; |
541 ec_pdo_entry_t *entry; |
521 unsigned int entry_count, i; |
542 unsigned int entry_count, i; |
522 |
543 |
523 while (word_count >= 4) { |
544 while (data_size >= 8) { |
524 if (!(pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) { |
545 if (!(pdo = kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) { |
525 EC_ERR("Failed to allocate PDO memory.\n"); |
546 EC_ERR("Failed to allocate PDO memory.\n"); |
526 return -1; |
547 return -1; |
527 } |
548 } |
528 |
549 |
532 entry_count = EC_READ_U8(data + 2); |
553 entry_count = EC_READ_U8(data + 2); |
533 pdo->sync_index = EC_READ_U8(data + 3); |
554 pdo->sync_index = EC_READ_U8(data + 3); |
534 pdo->name = ec_slave_sii_string(slave, EC_READ_U8(data + 5)); |
555 pdo->name = ec_slave_sii_string(slave, EC_READ_U8(data + 5)); |
535 list_add_tail(&pdo->list, &slave->sii_pdos); |
556 list_add_tail(&pdo->list, &slave->sii_pdos); |
536 |
557 |
537 word_count -= 4; |
558 data_size -= 8; |
538 data += 8; |
559 data += 8; |
539 |
560 |
540 for (i = 0; i < entry_count; i++) { |
561 for (i = 0; i < entry_count; i++) { |
541 if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) { |
562 if (!(entry = kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) { |
542 EC_ERR("Failed to allocate PDO entry memory.\n"); |
563 EC_ERR("Failed to allocate PDO entry memory.\n"); |
547 entry->subindex = EC_READ_U8(data + 2); |
568 entry->subindex = EC_READ_U8(data + 2); |
548 entry->name = ec_slave_sii_string(slave, EC_READ_U8(data + 3)); |
569 entry->name = ec_slave_sii_string(slave, EC_READ_U8(data + 3)); |
549 entry->bit_length = EC_READ_U8(data + 5); |
570 entry->bit_length = EC_READ_U8(data + 5); |
550 list_add_tail(&entry->list, &pdo->entries); |
571 list_add_tail(&entry->list, &pdo->entries); |
551 |
572 |
552 word_count -= 4; |
573 data_size -= 8; |
553 data += 8; |
574 data += 8; |
554 } |
575 } |
555 |
576 |
556 // if sync manager index is positive, the PDO is mapped by default |
577 // if sync manager index is positive, the PDO is mapped by default |
557 if (pdo->sync_index >= 0) { |
578 if (pdo->sync_index >= 0) { |
792 if (list_empty(&sync->pdos)) |
813 if (list_empty(&sync->pdos)) |
793 off += sprintf(buffer + off, " No PDOs mapped.\n"); |
814 off += sprintf(buffer + off, " No PDOs mapped.\n"); |
794 |
815 |
795 list_for_each_entry(pdo, &sync->pdos, list) { |
816 list_for_each_entry(pdo, &sync->pdos, list) { |
796 off += sprintf(buffer + off, " %s 0x%04X \"%s\"\n", |
817 off += sprintf(buffer + off, " %s 0x%04X \"%s\"\n", |
797 pdo->type == EC_RX_PDO ? "RXPDO" : "TXPDO", |
818 pdo->type == EC_RX_PDO ? "RxPdo" : "TxPdo", |
798 pdo->index, pdo->name ? pdo->name : "???"); |
819 pdo->index, pdo->name ? pdo->name : "???"); |
799 |
820 |
800 list_for_each_entry(pdo_entry, &pdo->entries, list) { |
821 list_for_each_entry(pdo_entry, &pdo->entries, list) { |
801 off += sprintf(buffer + off, |
822 off += sprintf(buffer + off, |
802 " 0x%04X:%X \"%s\", %i bit\n", |
823 " 0x%04X:%X \"%s\", %i bit\n", |
805 pdo_entry->bit_length); |
826 pdo_entry->bit_length); |
806 } |
827 } |
807 } |
828 } |
808 } |
829 } |
809 |
830 |
810 if (!list_empty(&slave->sii_pdos)) |
831 // type-cast to avoid warnings on some compilers |
|
832 if (!list_empty((struct list_head *) &slave->sii_pdos)) |
811 off += sprintf(buffer + off, "\nAvailable PDOs:\n"); |
833 off += sprintf(buffer + off, "\nAvailable PDOs:\n"); |
812 |
834 |
813 list_for_each_entry(pdo, &slave->sii_pdos, list) { |
835 list_for_each_entry(pdo, &slave->sii_pdos, list) { |
814 off += sprintf(buffer + off, " %s 0x%04X \"%s\"", |
836 off += sprintf(buffer + off, " %s 0x%04X \"%s\"", |
815 pdo->type == EC_RX_PDO ? "RXPDO" : "TXPDO", |
837 pdo->type == EC_RX_PDO ? "RxPdo" : "TxPdo", |
816 pdo->index, pdo->name ? pdo->name : "???"); |
838 pdo->index, pdo->name ? pdo->name : "???"); |
817 if (pdo->sync_index >= 0) |
839 if (pdo->sync_index >= 0) |
818 off += sprintf(buffer + off, ", default mapping: SM%u.\n", |
840 off += sprintf(buffer + off, ", default mapping: SM%u.\n", |
819 pdo->sync_index); |
841 pdo->sync_index); |
820 else |
842 else |
826 pdo_entry->name ? pdo_entry->name : "???", |
848 pdo_entry->name ? pdo_entry->name : "???", |
827 pdo_entry->bit_length); |
849 pdo_entry->bit_length); |
828 } |
850 } |
829 } |
851 } |
830 |
852 |
831 if (!list_empty(&slave->sdo_confs)) |
853 // type-cast to avoid warnings on some compilers |
|
854 if (!list_empty((struct list_head *) &slave->sdo_confs)) |
832 off += sprintf(buffer + off, "\nSDO configurations:\n"); |
855 off += sprintf(buffer + off, "\nSDO configurations:\n"); |
833 |
856 |
834 list_for_each_entry(sdodata, &slave->sdo_confs, list) { |
857 list_for_each_entry(sdodata, &slave->sdo_confs, list) { |
835 switch (sdodata->size) { |
858 switch (sdodata->size) { |
836 case 1: sprintf(str, "%i", EC_READ_U8(sdodata->data)); break; |
859 case 1: sprintf(str, "%i", EC_READ_U8(sdodata->data)); break; |
852 /** |
875 /** |
853 * Schedules an EEPROM write request. |
876 * Schedules an EEPROM write request. |
854 * \return 0 case of success, otherwise error code. |
877 * \return 0 case of success, otherwise error code. |
855 */ |
878 */ |
856 |
879 |
857 int ec_slave_schedule_eeprom_writing(ec_eeprom_write_request_t *request) |
880 int ec_slave_schedule_eeprom_writing( |
|
881 ec_eeprom_write_request_t *request /**< EEPROM write request */ |
|
882 ) |
858 { |
883 { |
859 ec_master_t *master = request->slave->master; |
884 ec_master_t *master = request->slave->master; |
860 |
885 |
861 request->state = EC_REQUEST_QUEUED; |
886 request->state = EC_REQUEST_QUEUED; |
862 |
887 |
887 } |
912 } |
888 |
913 |
889 /*****************************************************************************/ |
914 /*****************************************************************************/ |
890 |
915 |
891 /** |
916 /** |
|
917 * Calculates the EEPROM checksum field. |
|
918 * |
|
919 * The checksum is generated with the polynom x^8+x^2+x+1 (0x07) and an |
|
920 * initial value of 0xff (see IEC 61158-6-12 ch. 5.4). |
|
921 * |
|
922 * The below code was originally generated with PYCRC |
|
923 * http://www.tty1.net/pycrc |
|
924 * |
|
925 * ./pycrc.py --width=8 --poly=0x07 --reflect-in=0 --xor-in=0xff |
|
926 * --reflect-out=0 --xor-out=0 --generate c --algorithm=bit-by-bit |
|
927 * |
|
928 * \return CRC8 |
|
929 */ |
|
930 |
|
931 uint8_t ec_slave_eeprom_crc( |
|
932 const uint8_t *data, /**< pointer to data */ |
|
933 size_t length /**< number of bytes in \a data */ |
|
934 ) |
|
935 { |
|
936 unsigned int i; |
|
937 uint8_t bit, byte, crc = 0x48; |
|
938 |
|
939 while (length--) { |
|
940 byte = *data++; |
|
941 for (i = 0; i < 8; i++) { |
|
942 bit = crc & 0x80; |
|
943 crc = (crc << 1) | ((byte >> (7 - i)) & 0x01); |
|
944 if (bit) crc ^= 0x07; |
|
945 } |
|
946 } |
|
947 |
|
948 for (i = 0; i < 8; i++) { |
|
949 bit = crc & 0x80; |
|
950 crc <<= 1; |
|
951 if (bit) crc ^= 0x07; |
|
952 } |
|
953 |
|
954 return crc; |
|
955 } |
|
956 |
|
957 /*****************************************************************************/ |
|
958 |
|
959 /** |
892 * Writes complete EEPROM contents to a slave. |
960 * Writes complete EEPROM contents to a slave. |
893 * \return data size written in case of success, otherwise error code. |
961 * \return data size written in case of success, otherwise error code. |
894 */ |
962 */ |
895 |
963 |
896 ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */ |
964 ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */ |
900 { |
968 { |
901 ec_eeprom_write_request_t request; |
969 ec_eeprom_write_request_t request; |
902 const uint16_t *cat_header; |
970 const uint16_t *cat_header; |
903 uint16_t cat_type, cat_size; |
971 uint16_t cat_type, cat_size; |
904 int ret; |
972 int ret; |
|
973 uint8_t crc; |
905 |
974 |
906 if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME |
975 if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME |
907 EC_ERR("Writing EEPROMs only allowed in idle mode!\n"); |
976 EC_ERR("Writing EEPROMs only allowed in idle mode!\n"); |
908 return -EBUSY; |
977 return -EBUSY; |
909 } |
978 } |
914 } |
983 } |
915 |
984 |
916 // init EEPROM write request |
985 // init EEPROM write request |
917 INIT_LIST_HEAD(&request.list); |
986 INIT_LIST_HEAD(&request.list); |
918 request.slave = slave; |
987 request.slave = slave; |
919 request.words = (const uint16_t *) data; |
988 request.data = data; |
920 request.offset = 0; |
989 request.word_offset = 0; |
921 request.size = size / 2; |
990 request.word_size = size / 2; |
922 |
991 |
923 if (request.size < 0x0041) { |
992 if (request.word_size < 0x0041) { |
924 EC_ERR("EEPROM data too short! Dropping.\n"); |
993 EC_ERR("EEPROM data too short! Dropping.\n"); |
925 return -EINVAL; |
994 return -EINVAL; |
926 } |
995 } |
927 |
996 |
928 cat_header = request.words + EC_FIRST_EEPROM_CATEGORY_OFFSET; |
997 // calculate checksum |
|
998 crc = ec_slave_eeprom_crc(data, 14); // CRC over words 0 to 6 |
|
999 if (crc != data[14]) { |
|
1000 EC_WARN("EEPROM CRC incorrect. Must be 0x%02x.\n", crc); |
|
1001 } |
|
1002 |
|
1003 cat_header = (const uint16_t *) request.data |
|
1004 + EC_FIRST_EEPROM_CATEGORY_OFFSET; |
929 cat_type = EC_READ_U16(cat_header); |
1005 cat_type = EC_READ_U16(cat_header); |
930 while (cat_type != 0xFFFF) { // cycle through categories |
1006 while (cat_type != 0xFFFF) { // cycle through categories |
931 if (cat_header + 1 > request.words + request.size) { |
1007 if (cat_header + 1 > |
|
1008 (const uint16_t *) request.data + request.word_size) { |
932 EC_ERR("EEPROM data corrupted! Dropping.\n"); |
1009 EC_ERR("EEPROM data corrupted! Dropping.\n"); |
933 return -EINVAL; |
1010 return -EINVAL; |
934 } |
1011 } |
935 cat_size = EC_READ_U16(cat_header + 1); |
1012 cat_size = EC_READ_U16(cat_header + 1); |
936 if (cat_header + cat_size + 2 > request.words + request.size) { |
1013 if (cat_header + cat_size + 2 > |
|
1014 (const uint16_t *) request.data + request.word_size) { |
937 EC_ERR("EEPROM data corrupted! Dropping.\n"); |
1015 EC_ERR("EEPROM data corrupted! Dropping.\n"); |
938 return -EINVAL; |
1016 return -EINVAL; |
939 } |
1017 } |
940 cat_header += cat_size + 2; |
1018 cat_header += cat_size + 2; |
941 cat_type = EC_READ_U16(cat_header); |
1019 cat_type = EC_READ_U16(cat_header); |
960 size_t size /**< size of data in bytes */ |
1038 size_t size /**< size of data in bytes */ |
961 ) |
1039 ) |
962 { |
1040 { |
963 ec_eeprom_write_request_t request; |
1041 ec_eeprom_write_request_t request; |
964 char *remainder; |
1042 char *remainder; |
965 uint16_t alias, word; |
1043 uint16_t alias; |
966 int ret; |
1044 int ret; |
|
1045 uint8_t eeprom_data[16], crc; |
967 |
1046 |
968 if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME |
1047 if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME |
969 EC_ERR("Writing EEPROMs only allowed in idle mode!\n"); |
1048 EC_ERR("Writing to EEPROM is only allowed in idle mode!\n"); |
970 return -EBUSY; |
1049 return -EBUSY; |
971 } |
1050 } |
972 |
1051 |
973 alias = simple_strtoul(data, &remainder, 0); |
1052 alias = simple_strtoul(data, &remainder, 0); |
974 if (remainder == (char *) data || (*remainder && *remainder != '\n')) { |
1053 if (remainder == (char *) data || (*remainder && *remainder != '\n')) { |
975 EC_ERR("Invalid alias value! Dropping.\n"); |
1054 EC_ERR("Invalid alias value! Dropping.\n"); |
976 return -EINVAL; |
1055 return -EINVAL; |
977 } |
1056 } |
|
1057 |
|
1058 if (!slave->eeprom_data || slave->eeprom_size < 16) { |
|
1059 EC_ERR("Failed to read EEPROM contents from slave %u.\n", |
|
1060 slave->ring_position); |
|
1061 return -EINVAL; |
|
1062 } |
|
1063 |
|
1064 // copy first 7 words of recent EEPROM contents |
|
1065 memcpy(eeprom_data, slave->eeprom_data, 14); |
978 |
1066 |
979 // correct endianess |
1067 // write new alias address in word 4 |
980 EC_WRITE_U16(&word, alias); |
1068 EC_WRITE_U16(eeprom_data + 8, alias); |
|
1069 |
|
1070 // calculate new checksum over words 0 to 6 |
|
1071 crc = ec_slave_eeprom_crc(eeprom_data, 14); |
|
1072 EC_WRITE_U16(eeprom_data + 14, crc); |
981 |
1073 |
982 // init EEPROM write request |
1074 // init EEPROM write request |
983 INIT_LIST_HEAD(&request.list); |
1075 INIT_LIST_HEAD(&request.list); |
984 request.slave = slave; |
1076 request.slave = slave; |
985 request.words = &word; |
1077 request.data = eeprom_data; |
986 request.offset = 0x0004; |
1078 request.word_offset = 0x0000; |
987 request.size = 1; |
1079 request.word_size = 8; |
988 |
1080 |
989 if ((ret = ec_slave_schedule_eeprom_writing(&request))) |
1081 if ((ret = ec_slave_schedule_eeprom_writing(&request))) |
990 return ret; // error code |
1082 return ret; // error code |
991 |
1083 |
992 slave->sii_alias = alias; // FIXME: do this in state machine |
1084 slave->sii_alias = alias; // FIXME: do this in state machine |
1092 } |
1184 } |
1093 |
1185 |
1094 /*****************************************************************************/ |
1186 /*****************************************************************************/ |
1095 |
1187 |
1096 /** |
1188 /** |
|
1189 * Get the sync manager for either Rx- or Tx-PDOs. |
|
1190 * \return pointer to sync manager, or NULL. |
1097 */ |
1191 */ |
1098 |
1192 |
1099 ec_sync_t *ec_slave_get_pdo_sync( |
1193 ec_sync_t *ec_slave_get_pdo_sync( |
1100 ec_slave_t *slave, /**< EtherCAT slave */ |
1194 ec_slave_t *slave, /**< EtherCAT slave */ |
1101 ec_direction_t dir /**< input or output */ |
1195 ec_direction_t dir /**< input or output */ |
1205 |
1299 |
1206 *sdo_count = sdos; |
1300 *sdo_count = sdos; |
1207 *entry_count = entries; |
1301 *entry_count = entries; |
1208 } |
1302 } |
1209 |
1303 |
|
1304 /*****************************************************************************/ |
|
1305 |
|
1306 /** |
|
1307 * Get an SDO from the dictionary. |
|
1308 * \returns The desired SDO, of NULL. |
|
1309 */ |
|
1310 |
|
1311 ec_sdo_t *ec_slave_get_sdo( |
|
1312 ec_slave_t *slave /**< EtherCAT slave */, |
|
1313 uint16_t index /**< SDO index */ |
|
1314 ) |
|
1315 { |
|
1316 ec_sdo_t *sdo; |
|
1317 |
|
1318 list_for_each_entry(sdo, &slave->sdo_dictionary, list) { |
|
1319 if (sdo->index != index) continue; |
|
1320 return sdo; |
|
1321 } |
|
1322 |
|
1323 return NULL; |
|
1324 } |
|
1325 |
1210 /****************************************************************************** |
1326 /****************************************************************************** |
1211 * Realtime interface |
1327 * Realtime interface |
1212 *****************************************************************************/ |
1328 *****************************************************************************/ |
1213 |
1329 |
1214 /** |
1330 /** |
1263 return ec_slave_conf_sdo(slave, sdo_index, sdo_subindex, data, 4); |
1379 return ec_slave_conf_sdo(slave, sdo_index, sdo_subindex, data, 4); |
1264 } |
1380 } |
1265 |
1381 |
1266 /*****************************************************************************/ |
1382 /*****************************************************************************/ |
1267 |
1383 |
|
1384 /** |
|
1385 * Clear slave's PDO mapping. |
|
1386 */ |
|
1387 |
1268 void ecrt_slave_pdo_mapping_clear( |
1388 void ecrt_slave_pdo_mapping_clear( |
1269 ec_slave_t *slave, /**< EtherCAT slave */ |
1389 ec_slave_t *slave, /**< EtherCAT slave */ |
1270 ec_direction_t dir /**< output/input */ |
1390 ec_direction_t dir /**< output/input */ |
1271 ) |
1391 ) |
1272 { |
1392 { |
1279 |
1399 |
1280 if (!(sync = ec_slave_get_pdo_sync(slave, dir))) |
1400 if (!(sync = ec_slave_get_pdo_sync(slave, dir))) |
1281 return; |
1401 return; |
1282 |
1402 |
1283 ec_sync_clear_pdos(sync); |
1403 ec_sync_clear_pdos(sync); |
1284 } |
1404 sync->alt_mapping = 1; |
1285 |
1405 } |
1286 /*****************************************************************************/ |
1406 |
|
1407 /*****************************************************************************/ |
|
1408 |
|
1409 /** |
|
1410 * Add a PDO to the list of known mapped PDOs. |
|
1411 */ |
1287 |
1412 |
1288 int ecrt_slave_pdo_mapping_add( |
1413 int ecrt_slave_pdo_mapping_add( |
1289 ec_slave_t *slave, /**< EtherCAT slave */ |
1414 ec_slave_t *slave, /**< EtherCAT slave */ |
1290 ec_direction_t dir, /**< input/output */ |
1415 ec_direction_t dir, /**< input/output */ |
1291 uint16_t pdo_index /**< Index of PDO mapping list */) |
1416 uint16_t pdo_index /**< Index of mapped PDO */) |
1292 { |
1417 { |
1293 ec_pdo_t *pdo; |
1418 ec_pdo_t *pdo; |
1294 ec_sync_t *sync; |
1419 ec_sync_t *sync; |
1295 unsigned int not_found = 1; |
1420 unsigned int not_found = 1; |
1296 |
1421 |
1297 if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)) { |
1422 if (!(slave->sii_mailbox_protocols & EC_MBOX_COE)) { |
1298 EC_ERR("Slave %u does not support CoE!\n", slave->ring_position); |
1423 EC_ERR("Slave %u does not support CoE!\n", slave->ring_position); |
1299 return -1; |
1424 return -1; |
1300 } |
1425 } |
1301 |
1426 |
1302 // does the slave provide the PDO list? |
1427 // does the slave provide the PDO? |
1303 list_for_each_entry(pdo, &slave->sii_pdos, list) { |
1428 list_for_each_entry(pdo, &slave->sii_pdos, list) { |
1304 if (pdo->index == pdo_index) { |
1429 if (pdo->index == pdo_index) { |
1305 not_found = 0; |
1430 not_found = 0; |
1306 break; |
1431 break; |
1307 } |
1432 } |
1325 EC_ERR("Failed to obtain sync manager for PDO mapping of slave %u!\n", |
1450 EC_ERR("Failed to obtain sync manager for PDO mapping of slave %u!\n", |
1326 slave->ring_position); |
1451 slave->ring_position); |
1327 return -1; |
1452 return -1; |
1328 } |
1453 } |
1329 |
1454 |
1330 return ec_sync_add_pdo(sync, pdo); |
1455 if (ec_sync_add_pdo(sync, pdo)) |
1331 } |
1456 return -1; |
1332 |
1457 |
1333 /*****************************************************************************/ |
1458 sync->alt_mapping = 1; |
|
1459 return 0; |
|
1460 } |
|
1461 |
|
1462 /*****************************************************************************/ |
|
1463 |
|
1464 /** |
|
1465 * Convenience function for ecrt_slave_pdo_mapping_clear() and |
|
1466 * ecrt_slave_pdo_mapping_add(). |
|
1467 */ |
1334 |
1468 |
1335 int ecrt_slave_pdo_mapping(ec_slave_t *slave, /**< EtherCAT slave */ |
1469 int ecrt_slave_pdo_mapping(ec_slave_t *slave, /**< EtherCAT slave */ |
1336 ec_direction_t dir, /**< input/output */ |
1470 ec_direction_t dir, /**< input/output */ |
1337 unsigned int num_args, /**< Number of following arguments */ |
1471 unsigned int num_args, /**< Number of following arguments */ |
1338 ... /**< PDO indices to map */ |
1472 ... /**< PDO indices to map */ |