34 |
34 |
35 /*****************************************************************************/ |
35 /*****************************************************************************/ |
36 |
36 |
37 /** |
37 /** |
38 Konstruktor des EtherCAT-Masters. |
38 Konstruktor des EtherCAT-Masters. |
39 |
39 */ |
40 @param master Zeiger auf den zu initialisierenden EtherCAT-Master |
40 |
41 */ |
41 void ec_master_init(ec_master_t *master |
42 |
42 /**< Zeiger auf den zu initialisierenden EtherCAT-Master */ |
43 void ec_master_init(ec_master_t *master) |
43 ) |
44 { |
44 { |
45 master->bus_slaves = NULL; |
45 master->bus_slaves = NULL; |
46 master->bus_slaves_count = 0; |
46 master->bus_slaves_count = 0; |
47 master->device_registered = 0; |
47 master->device_registered = 0; |
48 master->command_index = 0x00; |
48 master->command_index = 0x00; |
60 /** |
60 /** |
61 Destruktor eines EtherCAT-Masters. |
61 Destruktor eines EtherCAT-Masters. |
62 |
62 |
63 Entfernt alle Kommandos aus der Liste, löscht den Zeiger |
63 Entfernt alle Kommandos aus der Liste, löscht den Zeiger |
64 auf das Slave-Array und gibt die Prozessdaten frei. |
64 auf das Slave-Array und gibt die Prozessdaten frei. |
65 |
65 */ |
66 @param master Zeiger auf den zu löschenden Master |
66 |
67 */ |
67 void ec_master_clear(ec_master_t *master |
68 |
68 /**< Zeiger auf den zu löschenden Master */ |
69 void ec_master_clear(ec_master_t *master) |
69 ) |
70 { |
70 { |
71 if (master->bus_slaves) { |
71 if (master->bus_slaves) { |
72 kfree(master->bus_slaves); |
72 kfree(master->bus_slaves); |
73 master->bus_slaves = NULL; |
73 master->bus_slaves = NULL; |
74 } |
74 } |
83 /** |
83 /** |
84 Setzt den Master in den Ausgangszustand. |
84 Setzt den Master in den Ausgangszustand. |
85 |
85 |
86 Bei einem "release" sollte immer diese Funktion aufgerufen werden, |
86 Bei einem "release" sollte immer diese Funktion aufgerufen werden, |
87 da sonst Slave-Liste, Domains, etc. weiter existieren. |
87 da sonst Slave-Liste, Domains, etc. weiter existieren. |
88 |
88 */ |
89 @param master Zeiger auf den zurückzusetzenden Master |
89 |
90 */ |
90 void ec_master_reset(ec_master_t *master |
91 |
91 /**< Zeiger auf den zurückzusetzenden Master */ |
92 void ec_master_reset(ec_master_t *master) |
92 ) |
93 { |
93 { |
94 if (master->bus_slaves) { |
94 if (master->bus_slaves) { |
95 kfree(master->bus_slaves); |
95 kfree(master->bus_slaves); |
96 master->bus_slaves = NULL; |
96 master->bus_slaves = NULL; |
97 } |
97 } |
110 /*****************************************************************************/ |
110 /*****************************************************************************/ |
111 |
111 |
112 /** |
112 /** |
113 Öffnet das EtherCAT-Geraet des Masters. |
113 Öffnet das EtherCAT-Geraet des Masters. |
114 |
114 |
115 @param master Der EtherCAT-Master |
115 \return 0, wenn alles o.k., < 0, wenn kein Gerät registriert wurde oder |
116 |
116 es nicht geoeffnet werden konnte. |
117 @return 0, wenn alles o.k., < 0, wenn das Geraet nicht geoeffnet werden |
117 */ |
118 konnte. |
118 |
119 */ |
119 int ec_master_open(ec_master_t *master /**< Der EtherCAT-Master */) |
120 |
|
121 int ec_master_open(ec_master_t *master) |
|
122 { |
120 { |
123 if (!master->device_registered) { |
121 if (!master->device_registered) { |
124 printk(KERN_ERR "EtherCAT: No device registered!\n"); |
122 printk(KERN_ERR "EtherCAT: No device registered!\n"); |
125 return -1; |
123 return -1; |
126 } |
124 } |
158 |
154 |
159 /** |
155 /** |
160 Sendet ein einzelnes Kommando in einem Frame und |
156 Sendet ein einzelnes Kommando in einem Frame und |
161 wartet auf dessen Empfang. |
157 wartet auf dessen Empfang. |
162 |
158 |
163 @param master EtherCAT-Master |
159 \return 0 bei Erfolg, sonst < 0 |
164 @param cmd Kommando zum Senden/Empfangen |
160 */ |
165 |
161 |
166 @return 0 bei Erfolg, sonst < 0 |
162 int ec_simple_send_receive(ec_master_t *master, |
167 */ |
163 /**< EtherCAT-Master */ |
168 |
164 ec_command_t *cmd |
169 int ec_simple_send_receive(ec_master_t *master, ec_command_t *cmd) |
165 /**< Kommando zum Senden/Empfangen */ |
|
166 ) |
170 { |
167 { |
171 unsigned int tries_left; |
168 unsigned int tries_left; |
172 |
169 |
173 if (unlikely(ec_simple_send(master, cmd) < 0)) |
170 if (unlikely(ec_simple_send(master, cmd) < 0)) |
174 return -1; |
171 return -1; |
192 /*****************************************************************************/ |
189 /*****************************************************************************/ |
193 |
190 |
194 /** |
191 /** |
195 Sendet ein einzelnes Kommando in einem Frame. |
192 Sendet ein einzelnes Kommando in einem Frame. |
196 |
193 |
197 @param master EtherCAT-Master |
194 \return 0 bei Erfolg, sonst < 0 |
198 @param cmd Kommando zum Senden |
195 */ |
199 |
196 |
200 @return 0 bei Erfolg, sonst < 0 |
197 int ec_simple_send(ec_master_t *master, /**< EtherCAT-Master */ |
201 */ |
198 ec_command_t *cmd /**< Kommando zum Senden */ |
202 |
199 ) |
203 int ec_simple_send(ec_master_t *master, ec_command_t *cmd) |
|
204 { |
200 { |
205 unsigned int length, framelength, i; |
201 unsigned int length, framelength, i; |
206 |
202 |
207 if (unlikely(master->debug_level > 0)) { |
203 if (unlikely(master->debug_level > 0)) { |
208 printk(KERN_DEBUG "EtherCAT: ec_simple_send\n"); |
204 printk(KERN_DEBUG "EtherCAT: ec_simple_send\n"); |
508 |
501 |
509 /** |
502 /** |
510 Liest Daten aus dem Slave-Information-Interface |
503 Liest Daten aus dem Slave-Information-Interface |
511 eines EtherCAT-Slaves. |
504 eines EtherCAT-Slaves. |
512 |
505 |
513 @param master EtherCAT-Master |
506 \return 0 bei Erfolg, sonst < 0 |
514 @param node_address Knotenadresse des Slaves |
507 */ |
515 @param offset Adresse des zu lesenden SII-Registers |
508 |
516 @param target Zeiger auf einen 4 Byte großen Speicher |
509 int ec_sii_read(ec_master_t *master, |
517 zum Ablegen der Daten |
510 /**< EtherCAT-Master */ |
518 |
511 unsigned short int node_address, |
519 @return 0 bei Erfolg, sonst < 0 |
512 /**< Knotenadresse des Slaves */ |
520 */ |
513 unsigned short int offset, |
521 |
514 /**< Adresse des zu lesenden SII-Registers */ |
522 int ec_sii_read(ec_master_t *master, unsigned short int node_address, |
515 unsigned int *target |
523 unsigned short int offset, unsigned int *target) |
516 /**< Zeiger auf einen 4 Byte großen Speicher zum Ablegen der |
|
517 Daten */ |
|
518 ) |
524 { |
519 { |
525 ec_command_t cmd; |
520 ec_command_t cmd; |
526 unsigned char data[10]; |
521 unsigned char data[10]; |
527 unsigned int tries_left; |
522 unsigned int tries_left; |
528 |
523 |
584 } |
579 } |
585 |
580 |
586 /*****************************************************************************/ |
581 /*****************************************************************************/ |
587 |
582 |
588 /** |
583 /** |
589 Ändert den Zustand eines Slaves (asynchron). |
584 Ändert den Zustand eines Slaves. |
590 |
585 |
591 Führt eine (asynchrone) Zustandsänderung bei einem Slave durch. |
586 \return 0 bei Erfolg, sonst < 0 |
592 |
587 */ |
593 @param master EtherCAT-Master |
588 |
594 @param slave Slave, dessen Zustand geändert werden soll |
589 int ec_state_change(ec_master_t *master, |
595 @param state_and_ack Neuer Zustand, evtl. mit gesetztem |
590 /**<EtherCAT-Master */ |
596 Acknowledge-Flag |
591 ec_slave_t *slave, |
597 |
592 /**< Slave, dessen Zustand geändert werden soll */ |
598 @return 0 bei Erfolg, sonst < 0 |
593 unsigned char state_and_ack |
599 */ |
594 /**< Neuer Zustand, evtl. mit gesetztem Acknowledge-Flag */ |
600 |
595 ) |
601 int ec_state_change(ec_master_t *master, ec_slave_t *slave, |
|
602 unsigned char state_and_ack) |
|
603 { |
596 { |
604 ec_command_t cmd; |
597 ec_command_t cmd; |
605 unsigned char data[2]; |
598 unsigned char data[2]; |
606 unsigned int tries_left; |
599 unsigned int tries_left; |
607 |
600 |
721 master->t_lost_output = t; |
710 master->t_lost_output = t; |
722 } |
711 } |
723 } |
712 } |
724 } |
713 } |
725 |
714 |
|
715 /*****************************************************************************/ |
|
716 |
|
717 /** |
|
718 Wandelt eine ASCII-kodierte Bus-Adresse in einen Slave-Zeiger. |
|
719 |
|
720 Gültige Adress-Strings sind Folgende: |
|
721 |
|
722 - \a "X" = der X. Slave im Bus, |
|
723 - \a "X:Y" = der Y. Slave hinter dem X. Buskoppler, |
|
724 - \a "#X" = der Slave mit der SSID X, |
|
725 - \a "#X:Y" = der Y. Slave hinter dem Buskoppler mit der SSID X. |
|
726 |
|
727 \return Zeiger auf Slave bei Erfolg, sonst NULL |
|
728 */ |
|
729 |
|
730 ec_slave_t *ec_address(const ec_master_t *master, |
|
731 /**< EtherCAT-Master */ |
|
732 const char *address |
|
733 /**< Address-String */ |
|
734 ) |
|
735 { |
|
736 unsigned long first, second; |
|
737 char *remainder, *remainder2; |
|
738 unsigned int i; |
|
739 int coupler_idx, slave_idx; |
|
740 ec_slave_t *slave; |
|
741 |
|
742 if (!address || address[0] == 0) return NULL; |
|
743 |
|
744 if (address[0] == '#') { |
|
745 printk(KERN_ERR "EtherCAT: Bus ID - #<SSID> not implemented yet!\n"); |
|
746 return NULL; |
|
747 } |
|
748 |
|
749 first = simple_strtoul(address, &remainder, 0); |
|
750 if (remainder == address) { |
|
751 printk(KERN_ERR "EtherCAT: Bus ID - First number empty!\n"); |
|
752 return NULL; |
|
753 } |
|
754 |
|
755 if (!remainder[0]) { // absolute position |
|
756 if (first < master->bus_slaves_count) { |
|
757 return master->bus_slaves + first; |
|
758 } |
|
759 |
|
760 printk(KERN_ERR "EtherCAT: Bus ID - Absolute position illegal!\n"); |
|
761 } |
|
762 |
|
763 else if (remainder[0] == ':') { // field position |
|
764 |
|
765 remainder++; |
|
766 second = simple_strtoul(remainder, &remainder2, 0); |
|
767 |
|
768 if (remainder2 == remainder) { |
|
769 printk(KERN_ERR "EtherCAT: Bus ID - Sencond number empty!\n"); |
|
770 return NULL; |
|
771 } |
|
772 |
|
773 if (remainder2[0]) { |
|
774 printk(KERN_ERR "EtherCAT: Bus ID - Illegal trailer (2)!\n"); |
|
775 return NULL; |
|
776 } |
|
777 |
|
778 coupler_idx = -1; |
|
779 slave_idx = 0; |
|
780 for (i = 0; i < master->bus_slaves_count; i++, slave_idx++) { |
|
781 slave = master->bus_slaves + i; |
|
782 if (!slave->type) continue; |
|
783 |
|
784 if (strcmp(slave->type->vendor_name, "Beckhoff") == 0 && |
|
785 strcmp(slave->type->product_name, "EK1100") == 0) { |
|
786 coupler_idx++; |
|
787 slave_idx = 0; |
|
788 } |
|
789 |
|
790 if (coupler_idx == first && slave_idx == second) return slave; |
|
791 } |
|
792 } |
|
793 |
|
794 else { |
|
795 printk(KERN_ERR "EtherCAT: Bus ID - Illegal trailer!\n"); |
|
796 } |
|
797 |
|
798 return NULL; |
|
799 } |
|
800 |
726 /****************************************************************************** |
801 /****************************************************************************** |
727 * |
802 * |
728 * Echtzeitschnittstelle |
803 * Echtzeitschnittstelle |
729 * |
804 * |
730 *****************************************************************************/ |
805 *****************************************************************************/ |
731 |
806 |
732 /** |
807 /** |
733 Registriert einen Slave beim Master. |
808 Registriert einen Slave beim Master. |
734 |
809 |
735 @param master Der EtherCAT-Master |
810 \return Zeiger auf den Slave bei Erfolg, sonst NULL |
736 @param bus_index Index des Slaves im EtherCAT-Bus |
|
737 @param vendor_name String mit dem Herstellernamen |
|
738 @param product_name String mit dem Produktnamen |
|
739 @param domain Domäne, in der der Slave sein soll |
|
740 |
|
741 @return Zeiger auf den Slave bei Erfolg, sonst NULL |
|
742 */ |
811 */ |
743 |
812 |
744 ec_slave_t *EtherCAT_rt_register_slave(ec_master_t *master, |
813 ec_slave_t *EtherCAT_rt_register_slave(ec_master_t *master, |
745 unsigned int bus_index, |
814 /**< EtherCAT-Master */ |
|
815 const char *address, |
|
816 /**< ASCII-Addresse des Slaves, siehe |
|
817 auch ec_address() */ |
746 const char *vendor_name, |
818 const char *vendor_name, |
|
819 /**< Herstellername */ |
747 const char *product_name, |
820 const char *product_name, |
748 int domain) |
821 /**< Produktname */ |
|
822 int domain |
|
823 /**< Domäne */ |
|
824 ) |
749 { |
825 { |
750 ec_slave_t *slave; |
826 ec_slave_t *slave; |
751 const ec_slave_type_t *type; |
827 const ec_slave_type_t *type; |
752 ec_domain_t *dom; |
828 ec_domain_t *dom; |
753 unsigned int j; |
829 unsigned int j; |
755 if (domain < 0) { |
831 if (domain < 0) { |
756 printk(KERN_ERR "EtherCAT: Invalid domain: %i\n", domain); |
832 printk(KERN_ERR "EtherCAT: Invalid domain: %i\n", domain); |
757 return NULL; |
833 return NULL; |
758 } |
834 } |
759 |
835 |
760 if (bus_index >= master->bus_slaves_count) { |
836 if ((slave = ec_address(master, address)) == NULL) { |
761 printk(KERN_ERR "EtherCAT: Illegal bus index! (%i / %i)\n", bus_index, |
837 printk(KERN_ERR "EtherCAT: Illegal address: \"%s\"\n", address); |
762 master->bus_slaves_count); |
|
763 return NULL; |
838 return NULL; |
764 } |
839 } |
765 |
840 |
766 slave = master->bus_slaves + bus_index; |
|
767 |
|
768 if (slave->registered) { |
841 if (slave->registered) { |
769 printk(KERN_ERR "EtherCAT: Slave %i is already registered!\n", bus_index); |
842 printk(KERN_ERR "EtherCAT: Slave \"%s\" (position %i) has already been" |
|
843 " registered!\n", address, slave->ring_position * (-1)); |
770 return NULL; |
844 return NULL; |
771 } |
845 } |
772 |
846 |
773 if (!slave->type) { |
847 if (!slave->type) { |
774 printk(KERN_ERR "EtherCAT: Unknown slave at position %i!\n", bus_index); |
848 printk(KERN_ERR "EtherCAT: Slave \"%s\" (position %i) has unknown type!\n", |
|
849 address, slave->ring_position * (-1)); |
775 return NULL; |
850 return NULL; |
776 } |
851 } |
777 |
852 |
778 type = slave->type; |
853 type = slave->type; |
779 |
854 |
827 /*****************************************************************************/ |
902 /*****************************************************************************/ |
828 |
903 |
829 /** |
904 /** |
830 Registriert eine ganze Liste von Slaves beim Master. |
905 Registriert eine ganze Liste von Slaves beim Master. |
831 |
906 |
832 @param master Der EtherCAT-Master |
907 \return 0 bei Erfolg, sonst < 0 |
833 @param slaves Array von Slave-Initialisierungsstrukturen |
|
834 @param count Anzahl der Strukturen in "slaves" |
|
835 |
|
836 @return 0 bei Erfolg, sonst < 0 |
|
837 */ |
908 */ |
838 |
909 |
839 int EtherCAT_rt_register_slave_list(ec_master_t *master, |
910 int EtherCAT_rt_register_slave_list(ec_master_t *master, |
|
911 /**< EtherCAT-Master */ |
840 const ec_slave_init_t *slaves, |
912 const ec_slave_init_t *slaves, |
841 unsigned int count) |
913 /**< Array von Slave-Initialisierungs- |
|
914 strukturen */ |
|
915 unsigned int count |
|
916 /**< Anzahl der Strukturen in \a slaves */ |
|
917 ) |
842 { |
918 { |
843 unsigned int i; |
919 unsigned int i; |
844 |
920 |
845 for (i = 0; i < count; i++) |
921 for (i = 0; i < count; i++) |
846 { |
922 { |
847 if ((*(slaves[i].slave_ptr) = |
923 if ((*(slaves[i].slave_ptr) = |
848 EtherCAT_rt_register_slave(master, slaves[i].bus_index, |
924 EtherCAT_rt_register_slave(master, slaves[i].address, |
849 slaves[i].vendor_name, |
925 slaves[i].vendor_name, |
850 slaves[i].product_name, |
926 slaves[i].product_name, |
851 slaves[i].domain)) == NULL) |
927 slaves[i].domain)) == NULL) |
852 return -1; |
928 return -1; |
853 } |
929 } |
862 |
938 |
863 Führt die komplette Konfiguration und Aktivierunge aller registrierten |
939 Führt die komplette Konfiguration und Aktivierunge aller registrierten |
864 Slaves durch. Setzt Sync-Manager und FMMU's, führt die entsprechenden |
940 Slaves durch. Setzt Sync-Manager und FMMU's, führt die entsprechenden |
865 Zustandsübergänge durch, bis der Slave betriebsbereit ist. |
941 Zustandsübergänge durch, bis der Slave betriebsbereit ist. |
866 |
942 |
867 @param master EtherCAT-Master |
943 \return 0 bei Erfolg, sonst < 0 |
868 |
944 */ |
869 @return 0 bei Erfolg, sonst < 0 |
945 |
870 */ |
946 int EtherCAT_rt_activate_slaves(ec_master_t *master /**< EtherCAT-Master */) |
871 |
|
872 int EtherCAT_rt_activate_slaves(ec_master_t *master) |
|
873 { |
947 { |
874 unsigned int i; |
948 unsigned int i; |
875 ec_slave_t *slave; |
949 ec_slave_t *slave; |
876 ec_command_t cmd; |
950 ec_command_t cmd; |
877 const ec_slave_type_t *type; |
951 const ec_slave_type_t *type; |
1096 /*****************************************************************************/ |
1168 /*****************************************************************************/ |
1097 |
1169 |
1098 /** |
1170 /** |
1099 Sendet und empfängt Prozessdaten der angegebenen Domäne |
1171 Sendet und empfängt Prozessdaten der angegebenen Domäne |
1100 |
1172 |
1101 @param master EtherCAT-Master |
1173 \return 0 bei Erfolg, sonst < 0 |
1102 @param domain Domäne |
1174 */ |
1103 @param timeout_us Timeout in Mikrosekunden |
1175 |
1104 |
1176 int EtherCAT_rt_domain_xio(ec_master_t *master, |
1105 @return 0 bei Erfolg, sonst < 0 |
1177 /**< EtherCAT-Master */ |
1106 */ |
1178 unsigned int domain, |
1107 |
1179 /**< Domäne */ |
1108 int EtherCAT_rt_domain_xio(ec_master_t *master, unsigned int domain, |
1180 unsigned int timeout_us |
1109 unsigned int timeout_us) |
1181 /**< Timeout in Mikrosekunden */ |
|
1182 ) |
1110 { |
1183 { |
1111 unsigned int i; |
1184 unsigned int i; |
1112 ec_domain_t *dom; |
1185 ec_domain_t *dom; |
1113 unsigned long start_ticks, end_ticks, timeout_ticks; |
1186 unsigned long start_ticks, end_ticks, timeout_ticks; |
1114 |
1187 |