53 master->command_index = 0x00; |
53 master->command_index = 0x00; |
54 master->tx_data_length = 0; |
54 master->tx_data_length = 0; |
55 master->process_data = NULL; |
55 master->process_data = NULL; |
56 master->process_data_length = 0; |
56 master->process_data_length = 0; |
57 master->cmd_ring_index = 0; |
57 master->cmd_ring_index = 0; |
|
58 master->debug_level = 0; |
58 |
59 |
59 for (i = 0; i < ECAT_COMMAND_RING_SIZE; i++) |
60 for (i = 0; i < ECAT_COMMAND_RING_SIZE; i++) |
60 { |
61 { |
61 EtherCAT_command_init(&master->cmd_ring[i]); |
62 EtherCAT_command_init(&master->cmd_ring[i]); |
|
63 master->cmd_reserved[i] = 0; |
62 } |
64 } |
63 |
65 |
64 return 0; |
66 return 0; |
65 } |
67 } |
66 |
68 |
75 @param master Zeiger auf den zu löschenden Master |
77 @param master Zeiger auf den zu löschenden Master |
76 */ |
78 */ |
77 |
79 |
78 void EtherCAT_master_clear(EtherCAT_master_t *master) |
80 void EtherCAT_master_clear(EtherCAT_master_t *master) |
79 { |
81 { |
80 EC_DBG("Master clear"); |
|
81 |
|
82 // Remove all pending commands |
82 // Remove all pending commands |
83 while (master->first_command) |
83 while (master->first_command) |
84 { |
84 { |
85 EtherCAT_remove_command(master, master->first_command); |
85 EtherCAT_remove_command(master, master->first_command); |
86 } |
86 } |
462 unsigned int wait_cycles; |
460 unsigned int wait_cycles; |
463 int i; |
461 int i; |
464 |
462 |
465 // Send all commands |
463 // Send all commands |
466 |
464 |
467 //EC_DBG("Master async send"); |
|
468 |
|
469 for (i = 0; i < ECAT_NUM_RETRIES; i++) |
465 for (i = 0; i < ECAT_NUM_RETRIES; i++) |
470 { |
466 { |
471 ASYNC = 1; |
467 ASYNC = 1; |
472 if (EtherCAT_send(master) < 0) return -1; |
468 if (EtherCAT_send(master) < 0) |
|
469 { |
|
470 return -1; |
|
471 } |
473 ASYNC = 0; |
472 ASYNC = 0; |
474 |
473 |
475 // Wait until something is received or an error has occurred |
474 // Wait until something is received or an error has occurred |
476 wait_cycles = 10; |
475 wait_cycles = 10; |
477 while (master->dev->state == ECAT_DS_SENT && wait_cycles) |
476 while (master->dev->state == ECAT_DS_SENT && wait_cycles) |
527 { |
526 { |
528 unsigned int i, length, framelength, pos; |
527 unsigned int i, length, framelength, pos; |
529 EtherCAT_command_t *cmd; |
528 EtherCAT_command_t *cmd; |
530 int cmdcnt = 0; |
529 int cmdcnt = 0; |
531 |
530 |
|
531 if (master->debug_level > 0) |
|
532 { |
|
533 EC_DBG(KERN_DEBUG "EtherCAT_send, first_command = %X\n", (int) master->first_command); |
|
534 } |
|
535 |
532 length = 0; |
536 length = 0; |
533 for (cmd = master->first_command; cmd != NULL; cmd = cmd->next) |
537 for (cmd = master->first_command; cmd != NULL; cmd = cmd->next) |
534 { |
538 { |
535 if (cmd->state != ECAT_CS_READY) continue; |
539 if (cmd->state != ECAT_CS_READY) continue; |
536 length += cmd->data_length + 12; |
540 length += cmd->data_length + 12; |
537 cmdcnt++; |
541 cmdcnt++; |
538 } |
542 } |
539 |
543 |
|
544 if (master->debug_level > 0) |
|
545 { |
|
546 EC_DBG(KERN_DEBUG "%i commands to send.\n", cmdcnt); |
|
547 } |
|
548 |
540 if (length == 0) |
549 if (length == 0) |
541 { |
550 { |
542 EC_DBG(KERN_WARNING "EtherCAT: Nothing to send...\n"); |
551 EC_DBG(KERN_WARNING "EtherCAT: Nothing to send...\n"); |
543 return 0; |
552 return 0; |
544 } |
553 } |
545 |
554 |
546 framelength = length + 2; |
555 framelength = length + 2; |
547 if (framelength < 46) framelength = 46; |
556 if (framelength < 46) framelength = 46; |
548 |
557 |
549 if (ASYNC && framelength > 46) |
558 if (master->debug_level > 0) |
550 EC_DBG(KERN_WARNING "Framelength: %d", framelength); |
559 { |
551 |
560 EC_DBG(KERN_DEBUG "framelength: %i\n", framelength); |
552 if (ASYNC && cmdcnt > 1) |
561 } |
553 EC_DBG(KERN_WARNING "CMDcount: %d", cmdcnt); |
|
554 |
562 |
555 master->tx_data[0] = length & 0xFF; |
563 master->tx_data[0] = length & 0xFF; |
556 master->tx_data[1] = ((length & 0x700) >> 8) | 0x10; |
564 master->tx_data[1] = ((length & 0x700) >> 8) | 0x10; |
557 pos = 2; |
565 pos = 2; |
558 |
566 |
560 { |
568 { |
561 if (cmd->state != ECAT_CS_READY) continue; |
569 if (cmd->state != ECAT_CS_READY) continue; |
562 |
570 |
563 cmd->index = master->command_index; |
571 cmd->index = master->command_index; |
564 master->command_index = (master->command_index + 1) % 0x0100; |
572 master->command_index = (master->command_index + 1) % 0x0100; |
|
573 |
|
574 if (master->debug_level > 0) |
|
575 { |
|
576 EC_DBG(KERN_DEBUG "Sending command index %i\n", cmd->index); |
|
577 } |
565 |
578 |
566 cmd->state = ECAT_CS_SENT; |
579 cmd->state = ECAT_CS_SENT; |
567 |
580 |
568 master->tx_data[pos + 0] = cmd->type; |
581 master->tx_data[pos + 0] = cmd->type; |
569 master->tx_data[pos + 1] = cmd->index; |
582 master->tx_data[pos + 1] = cmd->index; |
615 if ((i + 1) % 16 == 0) EC_DBG("\n" KERN_DEBUG); |
628 if ((i + 1) % 16 == 0) EC_DBG("\n" KERN_DEBUG); |
616 } |
629 } |
617 EC_DBG("\n"); |
630 EC_DBG("\n"); |
618 EC_DBG(KERN_DEBUG "-----------------------------------------------\n"); |
631 EC_DBG(KERN_DEBUG "-----------------------------------------------\n"); |
619 #endif |
632 #endif |
|
633 |
|
634 if (master->debug_level > 0) |
|
635 { |
|
636 EC_DBG(KERN_DEBUG "device send...\n"); |
|
637 } |
620 |
638 |
621 // Send frame |
639 // Send frame |
622 if (EtherCAT_device_send(master->dev, master->tx_data, framelength) != 0) |
640 if (EtherCAT_device_send(master->dev, master->tx_data, framelength) != 0) |
623 { |
641 { |
624 EC_DBG(KERN_ERR "EtherCAT: Could not send!\n"); |
642 EC_DBG(KERN_ERR "EtherCAT: Could not send!\n"); |
828 EtherCAT_command_init(cmd) |
851 EtherCAT_command_init(cmd) |
829 |
852 |
830 #define ECAT_FUNC_WRITE_FOOTER \ |
853 #define ECAT_FUNC_WRITE_FOOTER \ |
831 cmd->data_length = length; \ |
854 cmd->data_length = length; \ |
832 memcpy(cmd->data, data, length); \ |
855 memcpy(cmd->data, data, length); \ |
833 add_command(master, cmd); \ |
856 if (add_command(master, cmd) < 0) return NULL; \ |
834 return cmd |
857 return cmd |
835 |
858 |
836 #define ECAT_FUNC_READ_FOOTER \ |
859 #define ECAT_FUNC_READ_FOOTER \ |
837 cmd->data_length = length; \ |
860 cmd->data_length = length; \ |
838 add_command(master, cmd); \ |
861 if (add_command(master, cmd) < 0) return NULL; \ |
839 return cmd |
862 return cmd |
840 |
863 |
841 /***************************************************************/ |
864 /***************************************************************/ |
842 |
865 |
843 /** |
866 /** |
1073 int j; |
1096 int j; |
1074 |
1097 |
1075 for (j = 0; j < ECAT_COMMAND_RING_SIZE; j++) // Einmal rum suchen |
1098 for (j = 0; j < ECAT_COMMAND_RING_SIZE; j++) // Einmal rum suchen |
1076 { |
1099 { |
1077 // Solange suchen, bis freies Kommando gefunden |
1100 // Solange suchen, bis freies Kommando gefunden |
1078 if (master->cmd_ring[master->cmd_ring_index].reserved == 0) |
1101 if (master->cmd_reserved[master->cmd_ring_index] == 0) |
1079 { |
1102 { |
1080 master->cmd_ring[master->cmd_ring_index].reserved = 1; // Belegen |
1103 master->cmd_reserved[master->cmd_ring_index] = 1; // Belegen |
|
1104 |
|
1105 if (master->debug_level) |
|
1106 { |
|
1107 EC_DBG(KERN_DEBUG "Allocating command %i (addr %X).\n", |
|
1108 master->cmd_ring_index, |
|
1109 (int) &master->cmd_ring[master->cmd_ring_index]); |
|
1110 } |
|
1111 |
1081 return &master->cmd_ring[master->cmd_ring_index]; |
1112 return &master->cmd_ring[master->cmd_ring_index]; |
|
1113 } |
|
1114 |
|
1115 if (master->debug_level) |
|
1116 { |
|
1117 EC_DBG(KERN_DEBUG "Command %i (addr %X) is reserved...\n", |
|
1118 master->cmd_ring_index, |
|
1119 (int) &master->cmd_ring[master->cmd_ring_index]); |
1082 } |
1120 } |
1083 |
1121 |
1084 master->cmd_ring_index++; |
1122 master->cmd_ring_index++; |
1085 master->cmd_ring_index %= ECAT_COMMAND_RING_SIZE; |
1123 master->cmd_ring_index %= ECAT_COMMAND_RING_SIZE; |
1086 } |
1124 } |
1097 |
1135 |
1098 @param master EtherCAT-Master |
1136 @param master EtherCAT-Master |
1099 @param cmd Zeiger auf das einzufügende Kommando |
1137 @param cmd Zeiger auf das einzufügende Kommando |
1100 */ |
1138 */ |
1101 |
1139 |
1102 void add_command(EtherCAT_master_t *master, |
1140 int add_command(EtherCAT_master_t *master, |
1103 EtherCAT_command_t *cmd) |
1141 EtherCAT_command_t *new_cmd) |
1104 { |
1142 { |
1105 EtherCAT_command_t **last_cmd; |
1143 EtherCAT_command_t *cmd, **last_cmd; |
|
1144 |
|
1145 for (cmd = master->first_command; cmd != NULL; cmd = cmd->next) |
|
1146 { |
|
1147 if (cmd == new_cmd) |
|
1148 { |
|
1149 EC_DBG(KERN_WARNING "EtherCAT: Trying to add a command" |
|
1150 " that is already in the list!\n"); |
|
1151 return -1; |
|
1152 } |
|
1153 } |
1106 |
1154 |
1107 // Find the address of the last pointer in the list |
1155 // Find the address of the last pointer in the list |
1108 last_cmd = &(master->first_command); |
1156 last_cmd = &(master->first_command); |
1109 while (*last_cmd) last_cmd = &(*last_cmd)->next; |
1157 while (*last_cmd) last_cmd = &(*last_cmd)->next; |
1110 |
1158 |
1111 // Let this pointer point to the new command |
1159 // Let this pointer point to the new command |
1112 *last_cmd = cmd; |
1160 *last_cmd = new_cmd; |
|
1161 |
|
1162 return 0; |
1113 } |
1163 } |
1114 |
1164 |
1115 /***************************************************************/ |
1165 /***************************************************************/ |
1116 |
1166 |
1117 /** |
1167 /** |
1129 |
1179 |
1130 void EtherCAT_remove_command(EtherCAT_master_t *master, |
1180 void EtherCAT_remove_command(EtherCAT_master_t *master, |
1131 EtherCAT_command_t *rem_cmd) |
1181 EtherCAT_command_t *rem_cmd) |
1132 { |
1182 { |
1133 EtherCAT_command_t **last_cmd; |
1183 EtherCAT_command_t **last_cmd; |
|
1184 int i; |
1134 |
1185 |
1135 last_cmd = &master->first_command; |
1186 last_cmd = &master->first_command; |
1136 while (*last_cmd) |
1187 while (*last_cmd) |
1137 { |
1188 { |
1138 if (*last_cmd == rem_cmd) |
1189 if (*last_cmd == rem_cmd) |
1139 { |
1190 { |
1140 *last_cmd = rem_cmd->next; |
1191 *last_cmd = rem_cmd->next; |
1141 |
|
1142 EtherCAT_command_clear(rem_cmd); |
1192 EtherCAT_command_clear(rem_cmd); |
1143 |
1193 |
|
1194 // Reservierung des Kommandos aufheben |
|
1195 for (i = 0; i < ECAT_COMMAND_RING_SIZE; i++) |
|
1196 { |
|
1197 if (&master->cmd_ring[i] == rem_cmd) |
|
1198 { |
|
1199 master->cmd_reserved[i] = 0; |
|
1200 return; |
|
1201 } |
|
1202 } |
|
1203 |
|
1204 EC_DBG(KERN_WARNING "EtherCAT: Could not remove command reservation!\n"); |
1144 return; |
1205 return; |
1145 } |
1206 } |
1146 |
1207 |
1147 last_cmd = &(*last_cmd)->next; |
1208 last_cmd = &(*last_cmd)->next; |
1148 } |
1209 } |
1661 EtherCAT_command_clear(master->process_data_command); |
1714 EtherCAT_command_clear(master->process_data_command); |
1662 master->process_data_command = NULL; |
1715 master->process_data_command = NULL; |
1663 } |
1716 } |
1664 |
1717 |
1665 if ((master->process_data_command |
1718 if ((master->process_data_command |
1666 = EtherCAT_logical_read_write(master, 0, |
1719 = EtherCAT_logical_read_write(master, |
1667 master->process_data_length, |
1720 0, master->process_data_length, |
1668 master->process_data)) == NULL) |
1721 master->process_data)) == NULL) |
1669 { |
1722 { |
1670 EC_DBG(KERN_ERR "EtherCAT: Could not allocate process data command!\n"); |
1723 EC_DBG(KERN_ERR "EtherCAT: Could not allocate process data command!\n"); |
1671 return -1; |
1724 return -1; |
1672 } |
1725 } |
1730 } |
1783 } |
1731 |
1784 |
1732 /***************************************************************/ |
1785 /***************************************************************/ |
1733 |
1786 |
1734 /** |
1787 /** |
|
1788 Verwirft ein zuvor gesendetes Prozessdatenkommando. |
|
1789 |
|
1790 Diese Funktion sollte nach Ende des zyklischen Betriebes |
|
1791 aufgerufen werden, um das noch wartende Prozessdaten-Kommando |
|
1792 zu entfernen. |
|
1793 |
|
1794 @param master EtherCAT-Master |
|
1795 */ |
|
1796 |
|
1797 void EtherCAT_clear_process_data(EtherCAT_master_t *master) |
|
1798 { |
|
1799 if (!master->process_data_command) return; |
|
1800 |
|
1801 EtherCAT_remove_command(master, master->process_data_command); |
|
1802 EtherCAT_command_clear(master->process_data_command); |
|
1803 master->process_data_command = NULL; |
|
1804 } |
|
1805 |
|
1806 /***************************************************************/ |
|
1807 |
|
1808 /** |
1735 Setzt einen Byte-Wert im Speicher. |
1809 Setzt einen Byte-Wert im Speicher. |
1736 |
1810 |
1737 @param data Startadresse |
1811 @param data Startadresse |
1738 @param offset Byte-Offset |
1812 @param offset Byte-Offset |
1739 @param value Wert |
1813 @param value Wert |